数位dp
1.[hdu3709]Balanced Number
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue> 10 #include<map> 11 #include<set> 12 using namespace std; 13 #define FILE "dealing" 14 #define LL long long 15 #define up(i,j,n) for(LL i=(j);(i)<=(n);i++) 16 #define pii pair< LL , LL > 17 #define abs(x) ((x)<0?-(x):(x)) 18 #define max(x,y) ((x)>(y)?(x):(y)) 19 #define min(x,y) ((x)<(y)?(x):(y)) 20 namespace IO{ 21 char buf[1<<15],*fs,*ft; 22 LL gc(){return fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft),fs==ft?-1:*fs++;} 23 LL read(){ 24 LL x=0,ch=gc(),f=0; 25 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();} 26 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();} 27 return f?-x:x; 28 } 29 }using namespace IO; 30 bool chkmin(LL &a,LL b){return a>b?a=b,true:false;} 31 bool chkmax(LL &a,LL b){return a<b?a=b,true:false;} 32 const LL maxn(1000500),inf(100000000); 33 LL f[20][20][2500],now[20]; 34 LL dfs(LL pos,LL pivot,LL ans,LL limit){ 35 if(pos<1)return ans == 0; 36 if(ans<0)return 0; 37 if(!limit&&f[pos][pivot][ans]!=-1)return f[pos][pivot][ans]; 38 LL len=limit?now[pos]:9; 39 LL ret=0; 40 up(i,0,len)ret+=dfs(pos-1,pivot,ans+(pos-pivot)*i,limit&&i==len); 41 if(!limit)f[pos][pivot][ans]=ret; 42 return ret; 43 } 44 LL slove(LL x){ 45 now[0]=0; 46 while(x){now[++now[0]]=x%10;x/=10;} 47 LL ret=0; 48 up(i,1,now[0])ret+=dfs(now[0],i,0,1); 49 return ret-now[0]+1; 50 } 51 int main(){ 52 //freopen(FILE".in","r",stdin); 53 //freopen(FILE".out","w",stdout); 54 LL A,B; 55 LL T; 56 T=read(); 57 memset(f,-1,sizeof(f)); 58 while(T--){ 59 A=read();B=read(); 60 if(A==0)cout<<slove(B)<<endl; 61 else cout<<slove(B)-slove(A-1)<<endl; 62 } 63 return 0; 64 }
记忆化搜索
2,[hdu3555]只要49
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue> 10 #include<map> 11 #include<set> 12 using namespace std; 13 #define FILE "dealing" 14 #define LL long long 15 #define up(i,j,n) for(LL i=(j);(i)<=(n);i++) 16 #define pii pair< LL , LL > 17 #define abs(x) ((x)<0?-(x):(x)) 18 #define max(x,y) ((x)>(y)?(x):(y)) 19 #define min(x,y) ((x)<(y)?(x):(y)) 20 namespace IO{ 21 char buf[1<<15],*fs,*ft; 22 LL gc(){return fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft),fs==ft?-1:*fs++;} 23 LL read(){ 24 LL x=0,ch=gc(),f=0; 25 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();} 26 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();} 27 return f?-x:x; 28 } 29 }using namespace IO; 30 bool chkmin(LL &a,LL b){return a>b?a=b,true:false;} 31 bool chkmax(LL &a,LL b){return a<b?a=b,true:false;} 32 const LL maxn(1000500),inf(100000000); 33 LL f[50][10]; 34 void init(){ 35 up(i,0,9)f[1][i]=1; 36 up(i,2,20)up(j,0,9){ 37 up(k,0,9){ 38 if(j==4&&k==9)continue; 39 f[i][j]+=f[i-1][k]; 40 } 41 } 42 } 43 LL slove(LL x){ 44 LL now[21],ans=0,flag=0,y=x; 45 now[0]=0; 46 while(x){now[++now[0]]=x%10;x/=10;} 47 up(i,1,now[0]-1)up(j,1,9)ans+=f[i][j]; 48 up(i,1,now[now[0]]-1)ans+=f[now[0]][i]; 49 LL pre=now[now[0]]; 50 for(LL i=now[0]-1;i>=1;i--){ 51 if(now[i]==9&&now[i+1]==4)flag=1; 52 up(j,0,now[i]-1){ 53 if(now[i+1]==4&&j==9)continue; 54 ans+=f[i][j]; 55 } 56 if((now[i]==9&&now[i+1]==4))break; 57 pre=now[i]; 58 } 59 if(!flag&&y)ans++; 60 return ans; 61 } 62 int main(){ 63 //freopen(FILE".in","r",stdin); 64 //freopen(FILE".out","w",stdout); 65 init();LL A,B; 66 LL T; 67 T=read(); 68 while(T--){ 69 A=read(); 70 cout<<A-slove(A)<<endl; 71 } 72 return 0; 73 }
递推
3.[hdu2089]不要62
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue> 10 #include<map> 11 #include<set> 12 using namespace std; 13 #define FILE "dealing" 14 #define LL long long 15 #define up(i,j,n) for(int i=(j);(i)<=(n);i++) 16 #define pii pair< int , int > 17 #define abs(x) ((x)<0?-(x):(x)) 18 #define max(x,y) ((x)>(y)?(x):(y)) 19 #define min(x,y) ((x)<(y)?(x):(y)) 20 namespace IO{ 21 char buf[1<<15],*fs,*ft; 22 int gc(){return fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft),fs==ft?-1:*fs++;} 23 int read(){ 24 int x=0,ch=gc(),f=0; 25 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();} 26 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();} 27 return f?-x:x; 28 } 29 }using namespace IO; 30 bool chkmin(int &a,int b){return a>b?a=b,true:false;} 31 bool chkmax(int &a,int b){return a<b?a=b,true:false;} 32 const int maxn(1000500),inf(100000000); 33 int f[50][10]; 34 void init(){ 35 up(i,0,9)f[1][i]=1;f[1][4]=0; 36 up(i,2,10)up(j,0,9){ 37 if(j==4)continue; 38 up(k,0,9){ 39 if(j==6&&k==2)continue; 40 f[i][j]+=f[i-1][k]; 41 } 42 } 43 } 44 int slove(int x){ 45 int now[11],ans=0,flag=0; 46 now[0]=0; 47 if(x==0)return 0; 48 while(x){now[++now[0]]=x%10;x/=10;} 49 up(i,1,now[0]-1)up(j,1,9)ans+=f[i][j]; 50 up(i,1,now[now[0]]-1)ans+=f[now[0]][i]; 51 int pre=now[now[0]]; 52 if(pre==4)return ans; 53 for(int i=now[0]-1;i>=1;i--){ 54 if(now[i]==4||(now[i]==2&&now[i+1]==6))flag=1; 55 up(j,0,now[i]-1){ 56 if(now[i+1]==6&&j==2)continue; 57 ans+=f[i][j]; 58 } 59 if((now[i]==2&&now[i+1]==6)||now[i]==4)break; 60 pre=now[i]; 61 } 62 if(!flag)ans++; 63 return ans; 64 } 65 int main(){ 66 //freopen(FILE".in","r",stdin); 67 //freopen(FILE".out","w",stdout); 68 init();int A,B; 69 while(1){ 70 A=read(),B=read(); 71 if(A==0&&B==0)return 0; 72 printf("%d\n",slove(B)-slove(A-1)); 73 } 74 return 0; 75 }
递推
4.[haoi2010]计数
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cmath> 5 #include<cstring> 6 #include<ctime> 7 #include<iomanip> 8 #include<queue> 9 #include<map> 10 #include<set> 11 #include<algorithm> 12 using namespace std; 13 #define FILE "dealing" 14 #define LL long long 15 #define up(i,j,n) for(int i=(j);i<=(n);i++) 16 void chkmin(int &a,int b){a>b?a=b:0;} 17 void chkmax(int &a,int b){a<b?a=b:0;} 18 namespace IO{ 19 char buf[1<<15],*fs,*ft; 20 int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1<<15,1,stdin),fs==ft))?-1:*fs++;} 21 int read(){ 22 int x=0,f=0,ch=gc(); 23 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();} 24 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();} 25 return f?-x:x; 26 } 27 }using namespace IO; 28 const int maxn=52; 29 char s[maxn]; 30 int a[10],len; 31 LL fac[30],c[maxn][maxn]; 32 int main(){ 33 freopen(FILE".in","r",stdin); 34 freopen(FILE".out","w",stdout); 35 c[0][0]=1; 36 for(int i=1;i<=50;i++){ 37 c[i][0]=1; 38 for(int j=1;j<=50;j++)c[i][j]=c[i-1][j-1]+c[i-1][j]; 39 } 40 scanf("%s",s+1); 41 len=strlen(s+1); 42 up(i,1,len)a[s[i]-'0']++; 43 LL ans=0; 44 for(int i=1;i<=len;i++){ 45 for(int j=0;j<s[i]-'0';j++){ 46 if(!a[j])continue; 47 a[j]--; 48 int now=len-i; 49 LL sum=1; 50 for(int k=0;k<=9;k++) 51 sum*=c[now][a[k]],now-=a[k]; 52 ans+=sum; 53 a[j]++; 54 } 55 a[s[i]-'0']--; 56 } 57 cout<<ans<<endl; 58 return 0; 59 }
递推
通过这几道题的练习,对数位dp有了些理解;
数位dp的核心是按位确定,这些题无论约束条件如何,但本质不变;
有的约束条件用递推可以解决,于是可以预处理,有的约束条件比较复杂,需要记忆化;
数位dp也体现了dp的本质,每个数位其实就是一个阶段,每次搜索即将发散的时候,下面都有一个状态的承接,不至于时间爆炸;