【题解】 P4127 [AHOI2009]同类分布

\(Description:\)

给出两个数a,b,求出\([a,b]\)中各位数字之和能整除原数的数的个数。

$Sample $ \(Input:\)

10 19

\(Sample\) \(Output:\)

3

\(Solution:\)

设计状态 \(f[len][sum][res]\) 表示倒数还有 \(i\) 位要做,当前的和是 \(sum\) ,摸掉模数后剩下的数是 \(res\),

那么我们直接暴力枚举模数,\(len=0\) 最后判断一下是否 \(sum=mod\) \(\&\&\) \(res=0\) 这个时候可以吧答案返回为 \(1\)

那么再套个板子就。。。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a,b;
const int N=20+1,M=200+1;
int f[N][M][M],digit[N];
inline int dfs(int len,int sum,int res,int p,bool limit){
    if(len==0) {
        if(res==0) return (sum==p)?1:0;// 答案的判断,以为这样写可以加速,实际上变慢了。。。
        return 0;
    }
    if(!limit && f[len][sum][res]!=-1) return f[len][sum][res];
    int ret=0,up_bound=(limit)?digit[len]:9;
    for(int i=0;i<=up_bound;++i)
        ret+=dfs(len-1,sum+i,(res*10+i)%p,p,limit&&i==up_bound);
    return f[len][sum][res]=ret;
}
inline int solve(int n){
    int cnt=0,ret=0;
    while(n){
        digit[++cnt]=n%10;
        n/=10;
    }
    for(int p=1;p<=9*cnt;++p){//最多枚举到各位都是9
        memset(f,-1,sizeof(f));
        ret+=dfs(cnt,0,0,p,true);
    }
    return ret;
}
signed main(){
    scanf("%lld%lld",&a,&b);
    printf("%lld\n",solve(b)-solve(a-1));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/JCNL666/p/10712036.html