第一届 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;
}