[题解]luogu_P4127_同类分布(数位dp

如果像普通数位dp一样记的话我们需要知道这个数最后的数位和,然而我们并不能把它记到状态里,但是他的范围在18*9以内,所以枚举一下最后这个数的数位和,每次只统计数位和等于这个数的答案

还有就是有时候把前导0和lmt记到数组里会死,可能是我写挂了

#include
#define ll long long
using namespace std;
ll a,b;
ll f[20][200][200],num[20];//到i位数字和为j取余为k 
ll M;//枚举的模数 
ll dfs(int pos,int sum,int mod,bool lmt){
    if(pos==0)return (mod==0&&sum==M);
    if(!lmt&&f[pos][sum][mod]!=-1)return f[pos][sum][mod];
    int top=lmt?num[pos]:9;
    ll ans=0;
    for(int i=0;i<=top;i++)
    ans+=dfs(pos-1,sum+i,(mod*10+i)%M,lmt&&i==top);
    if(!lmt)f[pos][sum][mod]=ans;
    return ans;
}
ll work(ll x){
    ll tmp=x,cnt=0;
    while(tmp){
        num[++cnt]=tmp%10;
        tmp/=10;
    }
    ll ans=0;
    for(int i=1;i<=cnt*9;i++){
        memset(f,-1,sizeof(f));
        M=i;
        ans+=dfs(cnt,0,0,1);
    }
    return ans;
}
int main(){
    scanf("%lld%lld",&a,&b);
    printf("%lld",work(b)-work(a-1));
}

 

你可能感兴趣的:([题解]luogu_P4127_同类分布(数位dp)