poj3252 Round Numbers[数位DP]

地址

拆成2进制位做dp记搜就行了,带一下前导0,将0和1的个数带到状态里面,每种0和1的个数讨论一下,累加即可。

WA记录:line29。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define dbg(x) cerr<<#x<<" = "<<x<<endl
 7 
 8 using namespace std;
 9 typedef long long ll;
10 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
11 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
12 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
13 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
14 template<typename T>inline T read(T&x){
15     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
16     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
17 }
18 int f[33][33][33][2],b[33];
19 int l,r;
20 int dp(int len,int s0,int s1,bool lead,bool limit){//ddddbg(len,s0,s1,lead);dbg(limit);
21     if(s0<0||s1<0||s0+s1>len||(!lead&&(s0+s1)^len))return 0;
22     if(!len&&!s0&&!s1)return 1;
23     if(!limit&&~f[len][s0][s1][lead])return f[len][s0][s1][lead];
24     int cnt=0,num=limit?b[len]:1;
25     if(lead)cnt+=dp(len-1,s0,s1,1,limit&&!num);//填0
26     else cnt+=dp(len-1,s0-1,s1,0,limit&&!num);
27     if(num)cnt+=dp(len-1,s0,s1-1,0,limit);//填1 
28     return limit?cnt:f[len][s0][s1][lead]=cnt;
29 }//没有乖乖套模板卡上界判断写错了 
30 inline int solve(int x){
31     int k=0,cnt=0;while(x)b[++k]=x&1,x>>=1;
32 for(register int i=1;i<k;++i)for(register int j=1;j<=_min(i,k-i);++j)cnt+=dp(k,i,j,1,1); 33 return cnt; 34 } 35 36 int main(){//freopen("tmp.txt","r",stdin);//freopen("test.out","w",stdout); 37 memset(f,-1,sizeof f);read(l),read(r); 38 return printf("%d\n",solve(r)-solve(l-1)),0; 39 }

 

posted @ 2019-04-08 16:59  Ametsuji_akiya  阅读(100)  评论(0编辑  收藏  举报