LightOJ1032 Fast Bit Calculations(数位DP)

显然数位DP。

dp[i][j]表示所有末尾为j的i位二进制数相邻位的数量和

初始状态dp[2][1]=1

从长度i-1转移到长度i就是在i-1位的末尾添上0或1,转移方程就是:

dp[i][0]=dp[i-1][0]+dp[i-1][1]

dp[i][1]=dp[i-1][0]+dp[i-1][1]+2i-2

预处理完后,就可以通过这个计算出[0,n]区间的数量和,还是感觉数位DP的这一步挺棘手的,具体问题具体分析吧。。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 long long d[32][2];
 5 int main(){
 6     d[2][1]=1;
 7     for(int i=3; i<32; ++i){
 8         d[i][0]=d[i-1][0]+d[i-1][1];
 9         d[i][1]=d[i-1][0]+d[i-1][1]+(1<<i-2);
10     }
11     int t;
12     long long n;
13     scanf("%d",&t);
14     for(int cse=1; cse<=t; ++cse){
15         scanf("%lld",&n);
16         long long res=0;
17         for(int i=30; i>=0; --i){
18             if((n>>i)&1) res+=d[i][0]+d[i][1];
19             if(((n>>i)&1) && ((n>>i+1)&1)) res+=(n&((1LL<<i+2)-1))-((1<<i)|(1<<i+1))+1;
20         }
21         printf("Case %d: %lld\n",cse,res);
22     }
23     return 0;
24 }

 

posted @ 2016-01-13 16:24  WABoss  阅读(264)  评论(0编辑  收藏  举报