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\n",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\n");

132         else

133         printf("%I64d\n",cal(a-1,b));

134     }

135     return 0;

136 }
View Code

 

你可能感兴趣的:(count)