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 }