博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数位dp初探
阅读量:5293 次
发布时间:2019-06-14

本文共 5420 字,大约阅读时间需要 18 分钟。

我这种蒟蒻就一直不会写数位dp。。

于是开了个坑。。

1833: [ZJOI2010]count 数字计数

这道被KPM大爷说是入门题。。嗯似乎找找规律然后减掉0的情况后乱搞就可以了。。(但是还是写了很久TAT

#include
#include
#include
#include
#include
#include
#define rep(i,l,r) for (int i=l;i<=r;i++)#define down(i,l,r) for (int i=l;i>=r;i--)#define clr(x,y) memset(x,y,sizeof(x))#define low(x) (x&(-x)) #define maxn 505#define inf int(1e9)#define mm 1000000007#define ll long longusing namespace std;ll ans[10][2];ll a,b,bin[18];ll read(){ ll x=0,f=1; char ch=getchar(); while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f;}int get(ll x){ if (x==0) return 1; int ans=0; while(x){ans++; x/=10;} return ans;}void cal(ll x,int f){ int L,l=get(x),a; L=l; rep(i,0,9) ans[i][f]=(l-1)*bin[l-2]; rep(i,1,l-2) ans[0][f]-=bin[i]; while (l){ a=x/bin[l-1]; if (l==L) rep(i,1,a-1) { ans[i][f]+=bin[l-1]; if (l-2>=0) rep(j,0,9) ans[j][f]+=1LL*(l-1)*bin[l-2]; } if (l!=L) rep(i,0,a-1) { ans[i][f]+=bin[l-1]; if (l-2>=0) rep(j,0,9) ans[j][f]+=1LL*(l-1)*bin[l-2]; } ans[a][f]+=x%bin[l-1]+1; x=x%bin[l-1]; l--; }}int main(){ bin[0]=1; rep(i,1,13) bin[i]=bin[i-1]*10; a=read(); b=read(); cal(a-1,0); cal(b,1); rep(i,0,8) printf("%lld ",ans[i][1]-ans[i][0]); printf("%lld\n",ans[9][1]-ans[9][0]); return 0;}
View Code

1026: [SCOI2009]windy数

这道写个dp f[i][j]表示第i位最前一位数是j,特判一下0的情况。。

#include
#include
#include
#include
#include
#include
#define rep(i,l,r) for (int i=l;i<=r;i++)#define down(i,l,r) for (int i=l;i>=r;i--)#define clr(x,y) memset(x,y,sizeof(x))#define low(x) (x&(-x)) #define maxn 505#define inf int(1e9)#define mm 1000000007#define ll long longusing namespace std;int f[15][10],bin[15];int a,b;int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f;}int get(ll x){ if (x==0) return 1; int ans=0; while(x){ans++; x/=10;} return ans;}int cal(int x){ int L,l=get(x),ans=0,a,tmp=-100; L=l; if (l>1) ans++;//0的情况 rep(i,1,l-1) { rep(j,1,9) ans+=f[i][j]; } while (l){ a=x/bin[l-1]; if (l==L) rep(i,1,a-1) if (abs(i-tmp)>=2){ rep(j,0,9) if (abs(i-j)>=2) ans+=f[l-1][j]; } if (l!=L) rep(i,0,a-1) if (abs(i-tmp)>=2){ rep(j,0,9) if (abs(i-j)>=2) ans+=f[l-1][j]; } if (l==1) rep(i,0,a) if (abs(tmp-i)>=2) ans++; if (abs(tmp-a)<2) break; tmp=a; x%=bin[l-1]; l--; } return ans;}int main(){ bin[0]=1; rep(i,1,9) bin[i]=bin[i-1]*10; a=read(); b=read(); int l=get(b); rep(i,0,9) f[1][i]=1; rep(i,1,9) rep(j,0,9) if (f[i][j]){ rep(k,0,9) if (abs(j-k)>=2) f[i+1][k]+=f[i][j]; } printf("%d\n",cal(b)-cal(a-1)); return 0;}
View Code

1072: [SCOI2007]排列perm

为什么我一直认为这道是状压。。 f[s][i]表示当前状态是s,模数为i。然后枚举每一个数是否被选过转移就可以了。

最后除掉相同数字个数的阶乘。

#include
#include
#include
#include
#include
#include
#define rep(i,l,r) for (int i=l;i<=r;i++)#define down(i,l,r) for (int i=l;i>=r;i--)#define clr(x,y) memset(x,y,sizeof(x))#define low(x) (x&(-x)) #define maxn 505#define inf int(1e9)#define mm 1000000007#define ll long longusing namespace std;int f[1050][1005];int n,t,l,bin[20],a[20],num[20],p[20],ans;char s[15];int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f;}int main(){ t=read(); bin[0]=1; rep(i,1,10) bin[i]=bin[i-1]*2; p[0]=1; rep(i,1,10) p[i]=p[i-1]*i; while (t--){ clr(f,0); clr(num,0); scanf("%s",s); l=strlen(s); int d=read(); rep(i,0,l-1) a[i]=s[i]-'0',num[a[i]]++; //printf("%d\n",bin[l]-1); f[0][0]=1; rep(s,0,bin[l]-1) rep(j,0,d-1) if (f[s][j]){ rep(k,0,l-1) if ((s&bin[k])==0) f[s+bin[k]][(j*10+a[k])%d]+=f[s][j]; } ans=f[bin[l]-1][0]; rep(i,0,9) if (num[i]) ans/=p[num[i]]; printf("%d\n",ans); } return 0;}
View Code

2425: [HAOI2010]计数

题目其实就是给你一些数字让你用这些数字构造一个个比给定数小的数。。

比如说我现在这一位最高为x,那就取0~x-1(可以有前导0)为这一位然后剩下的数自由组合。

对于这个自由组合,比如剩下有n位,这个数字还剩下有x个,那每一次就乘上C(n,x)然后n-=x。

#include
#include
#include
#include
#include
#include
#define rep(i,l,r) for (int i=l;i<=r;i++)#define down(i,l,r) for (int i=l;i>=r;i--)#define clr(x,y) memset(x,y,sizeof(x))#define low(x) (x&(-x)) #define maxn 505#define inf int(1e9)#define mm 1000000007#define ll long longusing namespace std;ll c[55][55],ans;int cnt[10],a[55];char s[55];int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f;}ll cal(int n){ ll ans=1; int now=n; rep(i,0,9) ans*=c[now][cnt[i]],now-=cnt[i]; return ans; }int main(){ c[0][0]=1; rep(i,1,50) { c[i][0]=1; rep(j,1,50) c[i][j]=c[i-1][j-1]+c[i-1][j]; } scanf("%s",s); int l=strlen(s); rep(i,0,l-1) a[i+1]=s[i]-'0',cnt[a[i+1]]++; rep(i,1,l) { rep(j,0,a[i]-1) if (cnt[j]){ cnt[j]--; ans+=cal(l-i); cnt[j]++; } cnt[a[i]]--; } printf("%lld\n",ans); return 0;}
View Code

BZOJ1799: [Ahoi2009]self 同类分布

http://www.cnblogs.com/ctlchild/p/5126952.html

(还有几道题目慢慢填TAT。。。

转载于:https://www.cnblogs.com/ctlchild/p/5131420.html

你可能感兴趣的文章
【python】--迭代器生成器装饰器
查看>>
Pow(x, n)
查看>>
安卓当中的线程和每秒刷一次
查看>>
MySQL Proxy
查看>>
关于Vue的组件的通用性问题
查看>>
随机颜色值
查看>>
每日一库:Modernizr.js,es5-shim.js,es5-safe.js
查看>>
目录相关的操作
查看>>
解决虚拟机vmware安装64位系统“此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态”的问题...
查看>>
C++----练习--引用头文件
查看>>
11.基本包装类型
查看>>
ajax连接服务器框架
查看>>
wpf样式绑定 行为绑定 事件关联 路由事件实例
查看>>
利用maven管理项目之POM文件配置
查看>>
用HttpCombiner来减少js和css的请问次数
查看>>
FUSE-用户空间文件系统
查看>>
将tiff文件转化为jpg文件并保存
查看>>
ubuntu 16.04 开机脚本
查看>>
 VS2012 C#调用C++ dll
查看>>
TCL:表格(xls)中写入数据
查看>>