Uvalive-4494-(数位dp)

题意:求a->b中的二进制出现过多少个1,很显然的数位dp,对于某一位来说,如果这位是0,那么dp[i]=dp[i-1]  如果这一位是1 那么dp[i]=dp[i-1]+1<<(pos-1)+(后缀+1);

dp[pos][now] /pos表示当前的位,now表示现在是1还是0

 1 #include<bits/stdc++.h>
 2 
 3 #define inf 0x3f3f3f3f
 4 
 5 const int maxn=100;
 6 
 7 typedef long long LL;
 8 
 9 using namespace std;
10 
11 int a,b;
12 
13 int icase;
14 
15 LL dp[maxn+10][2];
16 
17 LL dig[maxn+10];
18 
19 int prefix[maxn+10];
20 
21 LL dfs(int pos,int limit,int now,int num){
22     if(pos<=1) return now==1;
23     if(dp[pos][now]!=-1&&!limit) return dp[pos][now];
24     int end=limit?dig[pos-1]:1;
25     LL ret=0;
26     if(!limit&&now==1) {
27         ret+=(1<<(pos-1));
28     }
29     if(limit&&now==1) {
30         ret+=(prefix[pos-1]+1);
31     }
32     for(int i=0;i<=end;i++){
33         ret+=dfs(pos-1,limit&&(i==end),i,num);
34     }
35     if(!limit)
36     return dp[pos][now]=ret;
37     else return ret;
38 }
39 
40 void solve(){
41    memset(prefix,0,sizeof(prefix));
42    memset(dp,-1,sizeof(dp));
43    memset(dig,0,sizeof(dig));
44    int len=0;
45    int x=a;
46    int y=b;
47    while(x){
48         dig[++len]=x%2;
49         if(x%2){
50         prefix[len]|=(1<<(len-1));
51         }
52         prefix[len]+=prefix[len-1];
53         x/=2;
54    }
55    LL ans1=0;
56    if(a>0)
57    ans1=dfs(len,1,1,a)+dfs(len,0,0,a);
58    else ans1=0;
59    memset(prefix,0,sizeof(prefix));
60    memset(dig,0,sizeof(dig));
61    memset(dp,-1,sizeof(dp));
62    len=0;
63    while(y){
64         dig[++len]=y%2;
65          if(y%2){
66         prefix[len]|=(1<<(len-1));
67         }
68         prefix[len]+=prefix[len-1];
69         y/=2;
70    }
71    LL ans2=0;
72    ans2=dfs(len,1,1,b)+dfs(len,0,0,b);
73   printf("Case %d: %lld\n",++icase,ans2-ans1);
74 }
75 
76 int main()
77 {
78     while(scanf("%d%d",&a,&b)!=EOF&&(a||b)){
79        a--;
80        solve();
81     }
82     return 0;
83 }

 

posted @ 2016-08-08 22:18  GeniusYang  阅读(204)  评论(0编辑  收藏  举报