1. 程式人生 > >BZOJ 1799: [Ahoi2009]self 同類分布 ( 數位dp )

BZOJ 1799: [Ahoi2009]self 同類分布 ( 數位dp )

初始化 int blank lin mat hid gif con +=

傳送門

也不是很難,微坑的一點是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

BZOJ 1799: [Ahoi2009]self 同類分布 ( 數位dp )