Fast Bit Calculations LightOJ - 1032
Fast Bit Calculations LightOJ - 1032
题意:求0到n的所有数的二进制表示中,"11"的总数量。(如果有连续的n(n>2)个1,记(n-1)个"11")
方法:常规数位dp。ans[pos][ans][f][pre0],pos当前位置,ans当前答案,f前一位,pre0是否在前导0
记一下看到的奇怪的做法:http://www.cnblogs.com/WABoss/p/5127652.html
错误(本地):
注意:按这种模板来写数位dp,要求将答案也记录进状态,其含义是当前面产生的答案相同,其他条件相同时,后面产生的答案也相同。
1 #include<cstdio> 2 #include<cstring> 3 typedef long long LL; 4 LL w[40],T,TT,n; 5 LL ans[40][40][2][2]; 6 LL dp(LL pos,LL f,bool pre0,bool limit,LL xx) 7 { 8 if(pos<1) return pre0?0:xx; 9 if(!limit&&ans[pos][xx][f][pre0]!=-1) 10 return ans[pos][xx][f][pre0]; 11 LL i,res=0,end=limit?w[pos]:1; 12 for(i=0;i<=end;i++) 13 res+=dp(pos-1,i,pre0&&i==0,limit&&i==w[pos],xx+(i==1&&f==1)); 14 return limit?res:ans[pos][xx][f][pre0]=res; 15 } 16 LL get(LL x) 17 { 18 LL i; 19 for(i=0;x>0;x/=2) w[++i]=x%2; 20 return dp(i,0,1,1,0); 21 } 22 int main() 23 { 24 memset(ans,-1,sizeof(ans)); 25 scanf("%lld",&T); 26 for(TT=1;TT<=T;TT++) 27 { 28 scanf("%lld",&n); 29 printf("Case %lld: %lld\n",TT,get(n)); 30 } 31 return 0; 32 }