第一届 acc 题解

初赛

数圈圈

转化成 16 进制统计一下

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 23;
int n , m ;

inline int read()
{
    int x = 0 , ch = getchar();
    while( ch < '0' || ch > '9' ) ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x ;
}

int main(){
    int t , n = read() , cnt = 0;
    while( n )
    {
        t = n % 16 , n /= 16;
        if( t == 0 || t == 4 || t == 6 || t == 9 || t == 10 || t == 13 )
            cnt ++;
        else if( t == 8 || t == 11 )
            cnt += 2;
    }
    cout << cnt << endl;
    return 0;
}

农田灌溉

找到最大的差即可

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 205;
int n , k , a[N] , len = 0;

inline int read()
{
    int x = 0 , ch = getchar();
    while( ch < '0' || ch > '9' ) ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x ;
}

void slove()
{
    n = read() , k = read() , a[1] = read() , len = 0;
    for( int i = 2 ; i <= k ; i ++ )
        a[i] = read() , len = max( len , a[i] - a[i-1] + 1 );
    len = len / 2 + ( len & 1 );
    len = max( len , a[1]);
    len = max( len , n - a[k] + 1 );
    printf("%d\n" , len );

}
int main(){
    int t = read();
    while(t --)
        slove();
    return 0;
}

选取数对

就是搜索就好了,但是需要加一些可行性剪枝

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 205;
int n , m , k;
ll a[N] , res;

inline int read()
{
    int x = 0 , ch = getchar();
    while( ch < '0' || ch > '9' ) ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x ;
}

void dfs( int x , int t , ll sum )
{
    if( t > k )
    {
        res = max( res , sum );
        return ;
    }
    if( x > n )
        return ;
    for( int i = x ; i <= n ; i ++ )
    {
        if( i + (k - t + 1 ) * m - 1 > n ) return ;// 剪枝
        dfs( i + m , t+1 , sum + a[i+m-1] - a[i-1] );
    }
}

int main(){
    n = read() , m = read() , k = read();
    for( int i = 1 ; i <= n ; i ++ )
        a[i] = read();
    for( int i = 1 ; i <= n ; i ++ )
        a[i] += a[i-1];
    dfs( 1 , 1 , 0 );
    cout << res << endl;
    return 0;
}

决赛

两个闹钟

有计算的方法,但是暴力的枚举然后设一个较大的上届就好了

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 1e6+5;
int a , b , c , d;


int read()
{
    int x = 0 , ch = getchar();
    while( ch < '0' || ch > '9' ) ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = (x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x;
}

int main()
{
    a = read() , b = read() , c = read() , d = read();
    while( b != d && b < 1e8 )
    {
        while( b < d ) b += a;
        while( d < b ) d += c;
    }
    if( b == d )
        cout << b << endl;
    else
        cout << -1 << endl;
    return 0;
}

合并石子

贪心的选择最小的合成方法就好了

如果对于[l,r]相等,如果存在[l,k]相等则[k+1,r]也一定相等,这样操作就可以使区间数加一,不断操作直到不能操作就是答案

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 1e6+5;
int n , m , a[N] , b[N] , k;

int read()
{
    int x = 0 , ch = getchar();
    while( ch < '0' || ch > '9' ) ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = (x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x;
}

int main()
{
    n = read() , m = read();
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    for( int i = 1 ; i <= m ; i ++ ) b[i] = read();
    int i = 1 , j = 1 , suma , sumb;

    while( i <= n && j <= m )
    {
        k ++ , suma = a[i] , sumb = b[j] , i ++ , j ++;
        while( suma != sumb )
        {
            while( suma < sumb ) suma += a[i++];
            while( sumb < suma ) sumb += b[j++];
        }
    }
    cout << k << endl;
    return 0;
}
posted @ 2022-04-11 20:56  PHarr  阅读(27)  评论(0编辑  收藏  举报