这题写的真是无比蛋疼啊,刚开始看,感觉像是数位dp,想了想,应该能做,那就搞吧,费了半天劲终于写完了,数据看起来也没啥问题了,交上去发现wa了,后来发现数据非常大的话就会超出long long的范围,这意思是要写高精啊,当时就郁闷了,没办法,又写了半天大整数加法和乘法,为了把之前的代码改成大整数的又弄了一会儿,写完真是累死人了。。。唉,这代码写的真是不忍直视,凑合看吧……
对于一个数,先将其转换为二进制。每个数可以用若干个模板和前缀表示,用f(m,b,d)表示这个数的结果,则m表示它的前缀中有多少个Adjacent Bits,b表示它前一位是1还是0,d表示这个数有多少个*,其中*可以表示0和1的任意一个数,比如110就可以用**、10*、110表示,分别对应f(0,0,2)、f(0,0,1)、f(1,0,0),这样就可以写出递推公式:
f(m,b,d)=f(m+(b==1?1:0),1,d-1)+f(m,0,d-1);
用dp[m][b][d]表示状态,将搜过的状态直接返回。
附上代码:
#include <iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #define inf 0x3f3f3f3f #define Inf 0x3FFFFFFFFFFFFFFFLL #define eps 1e-9 #define pi acos(-1.0) using namespace std; typedef long long ll; struct BigInt //自己写的大整数,比较挫,可以无视 { int num[50]; int len; void clear() { for(int i=0;i<50;++i) num[i]=0; len=1; } void getBigInt(ll n) { clear(); len=0; while(n!=0) { num[len++]=n%10; n/=10; } if(len==0) len=1; } void getBigInt(int n) { ll m=(ll)n; getBigInt(m); } BigInt operator + (const BigInt a)const { int n=max(len,a.len); BigInt c; c.clear(); c.len=0; int jinwei=0; int tp; for(int i=0;i<n;++i) { tp=a.num[i]+num[i]+jinwei; c.num[c.len++]=tp%10; jinwei=tp/10; } while(jinwei!=0) { c.num[c.len++]=jinwei%10; jinwei/=10; } return c; } BigInt operator * (const BigInt a) const { int m=a.len; int n=len; BigInt c; c.clear(); c.len=0; int bs=0,w=0,jinwei=0,tp; for(int i=0;i<m;++i) { jinwei=0; w=0; for(int j=0;j<n;++j) { tp=a.num[i]*num[j]+jinwei+c.num[bs+w]; c.num[bs+w]=tp%10; jinwei=tp/10; w++; } while(jinwei!=0) { c.num[bs+w]=jinwei%10; jinwei/=10; w++; } c.len=max(c.len,bs+w); bs++; } while(c.num[c.len-1]==0&&c.len>1) c.len--; return c; } }; BigInt dp[70][2][70]; BigInt pp[70]; int nu[100]; BigInt f(int m,int b,int d) { BigInt tp,td; tp.clear(); td.clear(); if(d<0) return tp; tp.getBigInt(m); if(d==0) return tp; if(d==1) { td.getBigInt(b==1?1:0); return td+pp[d]*tp; } if(d==2) { td.getBigInt(b==1?3:1); return td+pp[d]*tp; } if(dp[m][b][d].len>0) return dp[m][b][d]; dp[m][b][d].clear(); dp[m][b][d]=dp[m][b][d]+f(m+(b==1?1:0),1,d-1); dp[m][b][d]=dp[m][b][d]+f(m,0,d-1); return dp[m][b][d]; } BigInt slove(int n) { int m=0,b=0,d=n; BigInt res; res.clear(); //res+=f(0,0,n-1); for(int i=0;i<n;++i) { d--; if(nu[i]==1) { res=res+f(m,0,d); m+=(b==1)?1:0; b=1; } else { b=0; } } BigInt tp; tp.getBigInt(m); res=res+tp; return res; } void Init() { ll z=1; pp[0].getBigInt(z); for(int i=1;i<=63;++i) { z=z<<1; pp[i].getBigInt(z); } for(int i=0;i<70;++i) { for(int j=0;j<2;++j) { for(int k=0;k<70;++k) { dp[i][j][k].len=-1; } } } } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); Init(); int tcase=0; ll x; while(cin>>x) { if(x<0) break; tcase++; int len=0; while(x!=0) { nu[len++]=x%2; x=x>>1; } int temp; for(int i=0;i<len/2;++i) { temp=nu[i]; nu[i]=nu[len-i-1]; nu[len-i-1]=temp; } BigInt res=slove(len); cout<<"Case "<<tcase<<": "; for(int i=res.len-1;i>=0;--i) cout<<res.num[i]; cout<<endl; } return 0; }