BZOJ 1799: [Ahoi2009]self 同类分布 ( 数位dp )

传送门

 
也不是很难,微坑的一点是dp数组在扫描每一次数位和的时候都要初始化,
因为没有存 用来mod的总数位和x 的位置... ...
然后这个dp的式子也稍微想了一下...还是练题太少...
 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 using namespace std;
 8 const int upn=162;
 9 long long f[20][163][163]={};//k位 数位和 目前mod后值
10 long long shu[20]={};
11 long long a,b;
12 long long doit(int k,int x,int now,int modn,bool maxnum){
13     if(k==0){
14         return x==now&&modn==0;
15     }
16     if((!maxnum)&&f[k][x-now][modn]!=-1){
17         return f[k][x-now][modn];
18     }
19     int maxn=maxnum?shu[k]:9;
20     maxn=min(maxn,x-now);
21     int minn=0;
22     minn=max(minn,x-now-(k-1)*9);
23     long long ans=0;
24     int z;
25     for(int i=minn;i<=maxn;i++){
26         z=(modn*10+i)%x;
27         ans+=doit(k-1,x,now+i,z,maxnum&&i==shu[k]);
28     }
29     if(!maxnum){
30         f[k][x-now][modn]=ans;
31     }
32     return ans;
33 }
34 long long solve(long long x){
35     memset(shu,0,sizeof(shu));
36     memset(f,-1,sizeof(f));
37     if(x==0){
38         return 0;
39     }
40     int k=0;
41     while(x){
42         shu[++k]=x%10;
43         x/=10;
44     }
45     long long cnt=0;
46     for(int i=1;i<=9*k;i++){
47         cnt+=doit(k,i,0,0,1);
48     }
49     return cnt;
50 }
51 int main(){
52     memset(f,-1,sizeof(f));
53     scanf("%lld%lld",&a,&b);
54     printf("%lld\n",solve(b)-solve(a-1));
55     return 0;
56 }
View Code

 

posted @ 2017-11-04 17:04  鲸头鹳  阅读(119)  评论(0编辑  收藏  举报