1. 程式人生 > >AtCoder Tenka1 Programmer Beginner Contest 解題報告

AtCoder Tenka1 Programmer Beginner Contest 解題報告

賽時寫了ABC,D實在沒啥思路,然後C又難調...然後就從寫完AB時的32名掉到了150+名

T_T

碼力不夠,思維不行,我還是AFO吧

比賽連結

A - Measure

sb模擬,奇數串倒著輸出偶數串正著輸出

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f 
#define il inline 

#define in1(a) a=read()
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define
in4(a,b,c,d) in2(a,b),in2(c,d) #define out(a) printf( "%d" , a ) #define outn(a) out(a),putchar('\n') #define I_int int inline I_int read() { I_int x = 0 , f = 1 ; char c = getchar() ; while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
while( c >= '0' && c <= '9' ) { x = (x << 1) + (x << 3) + c - 48 ; c = getchar() ; } return x * f ; } #undef I_int using namespace std ; #define N 100010 char s[ N ] ; int main() { scanf( "%s" , s + 1 ) ; int len = strlen( s+1 ) ;
if( len == 2 ) puts( s + 1 ) ; else { for( int i = len ; i ; i -- ) putchar( s[ i ] ) ; } }
View Code

B - Exchange

還是模擬...按著題意的要求來就好,奇數一種情況偶數一種情況

然後一邊$+\frac{1}{2}$,一邊$-\frac{1}{2}$就好

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f 
#define il inline 

#define in1(a) a=read()
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
#define out(a) printf( "%d" , a ) 
#define outn(a) out(a),putchar('\n')

#define I_int int 
inline I_int read() {
    
    I_int x = 0 , f = 1 ; char c = getchar() ;
    while( c < '0' || c > '9' ) {
        if( c == '-' ) f = -1 ;
        c = getchar() ;
    }
    while( c >= '0' && c <= '9' ) {
        x = (x << 1) + (x << 3) + c - 48 ;
        c = getchar() ;
    }
    return x * f ;
}
#undef I_int

using namespace std ;

#define N 100010
int a[ 3 ] , k ;

int main() {
    in2( a[ 1 ] , a[ 0 ] ) ; in1( k ) ;
    for( int i = 1 ; i <= k ; i ++ ) {
        if( a[ i % 2 ] % 2 ) a[ i % 2 ] -- ;
        a[ ( i % 2 ) ^ 1 ] += a[ i % 2 ] / 2 ;
        a[ i % 2 ] -= a[ i % 2 ] / 2 ;
    }
    out( a[ 1 ] ) , putchar(' ') , outn( a[ 0 ] ) ; 
}
View Code

C - Align

很噁心的分類討論

首先要知道一個結論,最中間的數一定是最大或者最小的,然後我們可以在旁邊依次填入最大/次大/最小/次小的數

對串的奇偶分開討論(取mid的不同)

然後對於中間填最大還是填最小也要分開討論

然後綜合幾種情況取個最優就行

寫的有點長,實際上應該不用這麼多程式碼的QAQ

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f 
#define il inline 

#define in1(a) a=read()
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
#define out(a) printf( "%d" , a ) 
#define outn(a) out(a),putchar('\n')

#define I_int int 
inline I_int read() {
    
    I_int x = 0 , f = 1 ; char c = getchar() ;
    while( c < '0' || c > '9' ) {
        if( c == '-' ) f = -1 ;
        c = getchar() ;
    }
    while( c >= '0' && c <= '9' ) {
        x = (x << 1) + (x << 3) + c - 48 ;
        c = getchar() ;
    }
    return x * f ;
}
#undef I_int

using namespace std ;

#define N 100010

int n ;
int b[ N ] ;
int a[ N ] ;
ll ans = 0 ;

int main() {
    in1( n ) ;
    for( int i = 1 ; i <= n ; i ++ ) in1( a[ i ] ) ;
    sort( a+1 , a+n+1 ) ;
    int l = 1 , r = n , mid = ( l + r ) >> 1 ; 
    if( n % 2 ) {
        b[ mid ] = a[ r -- ] ;
        for( int i = mid - 1 ; i ; i -- ) {
            if( ( mid - i ) % 2 ) b[ i ] = a[ l ++ ] , b[ mid + mid - i ] = a[ l ++ ] ;
            else b[ i ] = a[ r -- ] , b[ mid + mid - i ] = a[ r -- ] ;
        }
        ll sum = 0 ;
        for( int i = 2 ; i <= n ; i ++ ) sum += abs( b[ i ] - b[ i - 1 ] ) ;
        ll t = sum ;
        l = 1  , r = n ;
        b[ mid ] = a[ l ++ ] ;
        for( int i = mid - 1 ; i ; i -- ) {
            if( ( mid - i ) % 2 == 0 ) b[ i ] = a[ l ++ ] , b[ mid + mid - i ] = a[ l ++ ] ;
            else b[ i ] = a[ r -- ] , b[ mid + mid - i ] = a[ r -- ] ;
        }
        sum = 0 ;
        for( int i = 2 ; i <= n ; i ++ ) sum += abs( b[ i ] - b[ i - 1 ] ) ;
        printf( "%lld\n" , max( t , sum ) ) ;
        return 0 ;
    }
    b[ mid ] = a[ r -- ] ;
    b[ mid + 1 ] = a[ l ++ ] ;
    for( int i = mid - 1 ; i ; i -- ) {
        if( ( mid - i ) % 2 ) b[ i ] = a[ l ++ ] , b[ n - i + 1 ] = a[ r -- ] ;
        else b[ i ] = a[ r -- ] , b[ n - i + 1 ] = a[ l ++ ] ;
    }
    ll sum = 0 , t = 0 ;
    for( int i = 2 ; i <= n ; i ++ ) {
        sum += abs( b[ i ] - b[ i - 1 ] ) ;
    }
    t = sum ;
    l = 1 , r = n ;
    b[ mid + 1 ] = a[ r -- ] ;
    b[ mid ] = a[ l ++ ] ;
    for( int i = mid - 1 ; i ; i -- ) {
        if( ( mid - i ) % 2 == 0 ) b[ i ] = a[ l ++ ] , b[ n - i + 1 ] = a[ r -- ] ;
        else b[ i ] = a[ r -- ] , b[ n - i + 1 ] = a[ l ++ ] ;
    }
    sum = 0 ;
    for( int i = 2 ; i <= n ; i ++ ) {
        sum += abs( b[ i ] - b[ i - 1 ] ) ;
    }
    printf( "%lld\n" , max( sum , t ) ) ; 
}
View Code

D - Crossing

寫這題之前一定要先讀懂題意

我比賽時一直讀錯題意,到結束時腦子裡想的還是錯誤的題意....然後就炸了

令k為所選子集的數量。

任何兩個子集的交集大小為1,並且為1,2,...,N中的任何一個元素也使用了兩次

對於選出來的子集的限制就是這樣的

我們不妨把這些子集抽象成點,交集抽象成邊,於是$1-n$這些元素就是邊的種類

那麼不難看出整個圖有$\frac{k(k-1)}{2}$條邊,並且邊的數目要等於n

於是可以枚舉出來這個k先,qzz大佬好像推了一個式子$O(1)$求出了這個k,不過我數學比較菜就直接枚舉了T_T

然後如果這個k列舉不出來就說明無解(一個比較玄學的地方,我從1列舉到n來判會WA掉第一個點,其他都沒問題,然後從1列舉到500就沒問題,不知道是怎麼回事)

然後來連邊

因為每個元素要溝通兩個子集

所以類似於完全圖那樣連邊就好

int x = 0 ;
for( int i = 0 ; i < k ; i ++ ) {
    for( int j = i + 1 ; j < k ; j ++ ) {
        x ++ ;
        s[ i ].push_back( x ) ;
        s[ j ].push_back( x ) ;
    }
}

然後就沒了

所以說這題的主要難度在於讀懂題意T_T

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f 
#define il inline 

#define in1(a) a=read()
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
#define out(a) printf( "%d" , a ) 
#define out_(a) printf( " %d" , a )
#define outn(a) out(a),putchar('\n')

#define I_int int 
inline I_int read() {

    I_int x = 0 , f = 1 ; char c = getchar() ;
    while( c < '0' || c > '9' ) {
        if( c == '-' ) f = -1 ;
        c = getchar() ;
    }
    while( c >= '0' && c <= '9' ) {
        x = (x << 1) + (x << 3) + c - 48 ;
        c = getchar() ;
    }
    return x * f ;
}
#undef I_int

using namespace std ;

#define N 100010

int n , k ;

vector<int>s[N]; 

int main() {
    in1( n ) ;
    k = -1 ;
    for( int i = 1 ; i < 500 ; i ++ ) 
        if( i * ( i - 1 ) / 2 == n ) { k = i ; break ; }
    if( k == -1 ) { return puts("No"),0; }
    int x = 0 ;
    for( int i = 0 ; i < k ; i ++ ) {
        for( int j = i + 1 ; j < k ; j ++ ) {
            x ++ ;
            s[ i ].push_back( x ) ;
            s[ j ].push_back( x ) ;
        }
    }
    puts("Yes"); outn(k);
    for( int i = 0 ; i < k ; i ++ ) {
        out((int)s[i].size());
        int len = s[ i ].size();
        for( int j = 0 ; j < len ; j ++ ) {
            out_(s[i][j]);
        }
        putchar('\n');
    }
    return 0 ;
}
View Code

還是太菜,還是要繼續努力啊QAQ