BZOJ1799: [Ahoi2009]self 同类分布
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1799
数位dp。。
f[i][o][k]表示当前第i位,模数为o,和为k。
然后转移就是f[i+1][o*10+j][k+j]+=f[i][o][k](j+k<=o)
然后枚举模数o统计。。。
注意符合条件的是取模后为0,加起来为o 。。
(跑得巨慢TAT
#include<cstring> #include<iostream> #include<cstdio> #include<queue> #include<cmath> #include<algorithm> #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 long using namespace std; ll bin[20]; ll f[19][175][175]; ll a,b,ans; 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){ int ans=0; while (x){ x/=10; ans++;} return ans; } ll cal(ll x,int o){ int a; int tmp1=0,tmp2=0; int l=get(x); ll ans=0; while (l){ a=x/bin[l-1]; rep(i,0,a-1) if (o-tmp2-i>=0) ans+=f[l-1][(o-(1LL*tmp1+1LL*i*bin[l-1]%o)%o)%o][o-tmp2-i]; else break; tmp2=tmp2+a; tmp1=(1LL*tmp1+1LL*a*bin[l-1])%o; x%=bin[l-1]; l--; } a=x; if ((tmp1+a)%o==0&&tmp2+a==o) ans++; return ans; } int main(){ bin[0]=1; rep(i,1,18) bin[i]=bin[i-1]*10; a=read(); b=read(); if (b==bin[18]) b--,ans++; int l=get(b); rep(o,1,l*9){ rep(i,0,l) rep(x,0,o) rep(k,0,o) f[i][x][k]=0; f[0][0][0]=1; rep(i,0,l-1) rep(x,0,o-1) rep(k,0,o) if (f[i][x][k]) { rep(j,0,9) if (j+k<=o) f[i+1][(x*10+j)%o][j+k]+=f[i][x][k]; } ans+=cal(b,o)-cal(a-1,o); } printf("%lld\n",ans); return 0; }