# 数位DP入坑
Hdu 2089 不要62
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } const int N=1e6+5; int n,m; int a[20],dgt; int f[20][2; int dfs(int dep,int pre,int sta,bool lim) { if(!dep) return 1; if(!lim&&f[dep][sta!=-1) return f[dep][sta]; int up=lim?a[dep]:9; int ans=0; for(int i=0;i<=up;++i) { if(i==4) continue; if(pre==6&&i==2) continue; ans+=dfs(dep-1,i,i==6,lim&&i==a[dep]); } if(!lim) f[dep][sta]=ans; return ans; } int solve(int x) { for(dgt=0;x;a[++dgt]=x%10,x/=10); return dfs(dgt,0,0,1); } int main() { while(1) { memset(f,-1,sizeof(f)); n=read(),m=read(); if(!n&&!m) break; cout<<solve(m)-solve(n-1)<<'\n'; } return 0; }
Hdu 6148 Valley Numer
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } const int N=105; const int mod=1e9+7; int T,n; char a[N]; int f[N][10][3]; int dfs(int dep,int pre,int turn,bool lim,bool invalid) { if(dep==n+1) return invalid?0:1; if(!lim&&f[dep][pre][turn]!=-1) return f[dep][pre][turn]; int up=lim?a[dep]-='0':9; int ans=0; for(int i=0;i<=up;++i) { if(turn==2&&i<pre) continue; int p=0; if(invalid) p=0; else if(i>pre) p=2; else if(i<pre) p=1; else p=turn; ans+=dfs(dep+1,i,p,lim&&i==a[dep],invalid&&i==0); ans%=mod; } if(!lim) f[dep][pre][turn]=ans; return ans; } int main() { T=read(); while(T--) { memset(f,-1,sizeof(f)); scanf("%s",a+1); n=strlen(a+1); cout<<dfs(1,0,0,1,1)<<'\n'; } return 0; }
Bzoj 1026: [SCOI2009]windy数
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; inline LL read() { char c=getchar();LL num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } LL A,B; LL a[100],dgt; LL f[100][10]; LL dfs(int dep,int pre,bool lim,bool invalid) { if(!dep) return invalid?0:1; if(!lim&&!invalid&&f[dep][pre]!=-1) return f[dep][pre]; int up=lim?a[dep]:9; LL ans=0; for(int i=0;i<=up;++i) { if(!invalid&&abs(i-pre)<2) continue; ans+=dfs(dep-1,i,lim&&i==a[dep],invalid&&i==0); } if(!lim&&!invalid) f[dep][pre]=ans; return ans; } LL solve(LL x) { for(dgt=0;x;a[++dgt]=x%10,x/=10); return dfs(dgt,0,1,1); } int main() { A=read(),B=read(); memset(f,-1,sizeof(f)); cout<<solve(B)-solve(A-1); return 0; }
Poj 3252 Round Numbers
题意:问[l,r]中二进制位1比0少的数有多少个。
Sol: 记录当前层0,1个数。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } int l,r; int a[65],bit; int f[65][65][65]; int dfs(int dep,int c0,int c1,bool lim,bool invalid) { if(!dep) return (!invalid&&c0>=c1)?1:0; if(!lim&&f[dep][c0][c1]!=-1) return f[dep][c0][c1]; int up=lim?a[dep]:1; int ans=0; for(int i=0;i<=up;++i) ans+=dfs(dep-1,c0+(i==0&&!invalid),c1+(i==1),lim&&i==up,invalid&&i==0); if(!lim) f[dep][c0][c1]=ans; return ans; } int solve(int x) { for(bit=0;x;a[++bit]=x&1,x>>=1); return dfs(bit,0,0,1,1); } int main() { memset(f,-1,sizeof(f)); l=read(),r=read(); cout<<solve(r)-solve(l-1); return 0; }
P2518 [HAOI2010]计数
一个比较假的数位DP?但也是按照数位来做的。
Sol:无。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } char num[61]; LL ans;int n,m; int a[61],cnt[10]; LL c[60][60]; void init() { c[0][0]=1; for(int i=1;i<=50;++i) { c[i][0]=1; for(int j=1;j<=i;++j) c[i][j]=c[i-1][j-1]+c[i-1][j]; } } LL C(int n) { LL res=1; for(int i=0;i<10;++i) if(cnt[i]) res*=c[n][cnt[i]],n-=cnt[i]; return res; } int main() { init(); scanf("%s",num+1); for(n=1;num[n];++n) a[n]=num[n]-'0',++cnt[num[n]-'0']; m=--n; for(int i=1;i<=n;++i) { --m; for(int j=0;j<a[i];++j) if(cnt[j]) --cnt[j],ans+=C(m),++cnt[j]; --cnt[a[i]]; } cout<<ans; return 0; }