去年南京邀请赛的水题,当时找规律过的,看它长得很像数位dp,试了试用数位dp能不能过,d出每位上有多少个1,然后TLE了。。然后用规律优化了前4位,勉强过了。
附数位dp代码及找规律代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<stack> 7 #include<cmath> 8 #include<stdlib.h> 9 #include<map> 10 using namespace std; 11 #define N 1000000 12 #define LL __int64 13 int dp[35][35][2]; 14 int di[35],o[35],oo[35]; 15 int s[N][35],tg,pp[33]; 16 bool f[N]; 17 int dfs(int i,int e,bool z,int k) 18 { 19 if(i<0) return z; 20 if(!e&&dp[i][k][z]!=-1) return dp[i][k][z]; 21 int mk = e?di[i]:1; 22 int ans = 0; 23 for(int j = 0; j <= mk ; j++) 24 { 25 int ct = dfs(i-1,e&&(j==mk),(z|((i==k)&&j)),k); 26 ans+=ct; 27 } 28 return e?ans:dp[i][k][z] = ans; 29 } 30 int cc(int x,int k) 31 { 32 int p1 = (x-pp[k]+1)/pp[k+1]; 33 int qq = p1*pp[k]; 34 if((x-pp[k]+1)%pp[k+1]>pp[k]) qq += pp[k]; 35 else qq+=((x-pp[k]+1)%pp[k+1]); 36 return qq; 37 } 38 //void cal(int x,int y) 39 //{ 40 // int g = 0,i; 41 // int tx = x; 42 // memset(o,0,sizeof(o)); 43 // if(x<=0) 44 // o[0] = o[1] = 0; 45 // else{ 46 // o[0] = (x+1)/2; 47 // o[1] = cc(x,1); 48 // if(x>=3) 49 // o[2] = cc(x,2); 50 // if(x>=7) 51 // o[3] = cc(x,3); 52 // } 53 // while(x>0) 54 // { 55 // di[g++] = x%2; 56 // x/=2; 57 // } 58 // for(i = 4 ; i <= g-1 ; i++) 59 // { 60 // o[i] = dfs(g-1,1,0,i); 61 // } 62 // int t = 0; 63 // LL ans = 0; 64 // if(y<=0) 65 // oo[0] = oo[1] = o[2] = o[3] = 0; 66 // else{ 67 // oo[0] = ((y+1)/2); 68 // oo[1] = cc(y,1); 69 // if(y>=3) 70 // oo[2] = cc(y,2); 71 // if(y>=7) 72 // oo[3] = cc(y,3); 73 // } 74 // g = 0; 75 // while(y) 76 // { 77 // di[g++] = y%2; 78 // y/=2; 79 // } 80 // for(i = 4 ;i <= g-1 ; i++) 81 // { 82 // oo[i] = dfs(g-1,1,0,i); 83 // } 84 // for(i = 0 ; i <= g-1; i++) 85 // { 86 // t = (t+oo[i]-o[i])/2; 87 // ans+=t; 88 // } 89 // while(t) 90 // { 91 // t = (t)/2; 92 // ans+=t; 93 // } 94 // printf("%I64d ",ans); 95 //} 96 LL cal(int a,int b) 97 { 98 LL ans = 0; 99 int t = 0,s1,s2; 100 if(a>=0) s1 = (a+1)/2; 101 if(b>=0) s2 = (b+1)/2; 102 t = (s2-s1)/2; 103 ans+=t; 104 for(int i = 1 ;i < 31 ;i++) 105 { 106 if(a>=pp[i]) s1 = cc(a,i); 107 else s1=0; 108 if(b>=pp[i]) s2 = cc(b,i); 109 else s2=0; 110 t = (t+s2-s1)/2; 111 ans+=t; 112 } 113 while(t) 114 { 115 t/=2; 116 ans+=t; 117 } 118 return ans; 119 } 120 int main() 121 { 122 int a,b; 123 pp[0] = 1; 124 for(int i = 1; i < 32 ; i++) 125 pp[i] = pp[i-1]*2; 126 memset(dp,-1,sizeof(dp)); 127 int t = 0; 128 while(scanf("%d%d",&a,&b)!=EOF) 129 { 130 if(a==b) 131 printf("0 "); 132 else 133 printf("%I64d ",cal(a-1,b)); 134 } 135 return 0; 136 }