Dまでは順調だったんだけどね。
https://codeforces.com/contest/2173/problem/D
問題
整数N,Kが与えられる。
Nに2の累乗を1つ選んで加算する、という作業をK回繰り返す。
Nを2進数とみなしたとき、繰り上げの回数の総和の最大値を求めよ。
解法
Nを2進数表記したとき、少なくともどこか1か所はビットが立っているので、そのうちどこかに合わせた2の累乗を加算するとよい。
この作業を繰り返すと、Nはいずれ2の累乗になる。
その後は1回の作業で1回繰り上がり確定である。
よって、それまでの間、具体的にはNが2^30を超えるまでの間、どこで加算すると繰り上がり回数が最大になるかをDPで求めよう。
int T; int N,K; int dp[32][32][2]; void solve() { int i,j,k,l,r,x,y; string s; cin>>T; while(T--) { cin>>N>>K; FOR(x,32) FOR(y,32) dp[x][y][0]=dp[x][y][1]=-1<<30; dp[0][0][0]=0; FOR(x,30) FOR(y,30) FOR(k,2) { if((N>>x)%2+k>=2) { dp[x+1][y][1]=max(dp[x+1][y][1],dp[x][y][k]+1); } if((N>>x)%2+k>=1) { dp[x+1][y+1][1]=max(dp[x+1][y+1][1],dp[x][y][k]+1); } dp[x+1][y][0]=max(dp[x+1][y][0],dp[x][y][k]); } int ret=0; FOR(i,31) if(i<=K) { ret=max(ret,dp[30][i][0]); ret=max(ret,dp[30][i][1]+K-i); } cout<<ret<<endl; } }
まとめ
ここはすんなり。