P4127 [AHOI2009]同类分布
P4127 [AHOI2009]同类分布
题解
好的,敲上数位DP DFS板子
记录一下填的各位数字之和 sum ,然后记录一下原数 yuan
最后判断一下 yuan%sum==0 不就好啦???
突然意识到 dp 数组咋存???
dp[pos][sum][yuan]
pos , sum 都可以记录,但是 yuan ??? 1e18???
我们可以把yuan取模啊!
yuan%mod ?
取模啥呢???如果固定一个取模数字,结果很有可能就不对了,那就枚举吧
看到原式 yuan%sum ?= 0
mod = 1~sum 好啦
yuan%mod = 0 并且 sum=mod 不就相当于 yuan%sum==0 么
所以 dp[pos][sum][yuan%mod]
代码
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; inline ll read() { ll ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } ll a,b; ll c[20],len=0; ll dp[20][200][200]; ll mod; ll dfs(ll pos,ll sum,ll k,ll yuan,bool limit,bool qdl) { if(pos<=0) return sum==mod&&k==0; if(!limit&&!qdl&&dp[pos][sum][k]!=-1) return dp[pos][sum][k]; ll ans=0; ll up=limit?c[pos]:9; for(ll i=0;i<=up;i++) ans+=dfs(pos-1,sum+i,(yuan*10+i)%mod,yuan*10+i,limit&&(i==up),qdl&&(i==0)); if(!limit&&!qdl) dp[pos][sum][k]=ans; return ans; } ll fun(ll x) { memset(c,0,sizeof(c));len=0; while(x) { c[++len]=x%10; x/=10; } ll ans=0; for(mod=1;mod<=len*9;mod++) { memset(dp,-1,sizeof(dp)); ans+=dfs(len,0,0,0,1,1); } return ans; } int main() { a=read();b=read(); printf("%lld\n",fun(b)-fun(a-1)); return 0; }