题意:求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 }
时间: 2024-11-09 15:26:33