hdu4588Count The Carries

链接

去年南京邀请赛的水题,当时找规律过的,看它长得很像数位dp,试了试用数位dp能不能过,d出每位上有多少个1,然后TLE了。。然后用规律优化了前4位,勉强过了。

附数位dp代码及找规律代码。

  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 }
View Code
原文地址:https://www.cnblogs.com/shangyu/p/3802805.html