P4127 同类分布

题目链接:https://www.luogu.com.cn/problem/P4127

思路:数位dp,可以枚举各个位的数字之和mod,然后在dfs时记录各个数字之和s,以及这个数字sum。其他地方差不多,具体可以看代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[20][205][205];
int a[20];
int mod;
//len代表当前枚举的位,s表示各个数字之和,sum表示数字的值,flag代表是否还是处于上边界
ll dfs(int len,int s,int sum,bool flag)
{
    if(len==0)
    {
        if(s==0)//全为前导0
            return 0;
        if(sum==0&&s==mod)
            return 1;
        return 0;
    }
    int up=flag?a[len]:9;//决定你枚举的上界是多少
    if(!flag&&dp[len][s][sum]!=-1)
        return dp[len][s][sum];//如果不是处于上边界并且之前求过了值的话可以直接返回
    ll tmp=0;
    for(int i=0; i<=up; i++)
    {
        tmp+=dfs(len-1,s+i,(sum*10+i)%mod,flag&&i==up);
    }
    if(!flag)
        dp[len][s][sum]=tmp;//求了值用dp存下,下次可以使用
    return tmp;
}
ll fun(ll x)
{
    int pos=0;
    while(x)
    {
        a[++pos]=x%10;
        x/=10;
    }
    ll ans=0;
    for(mod=1;mod<=pos*9;mod++)//枚举模数
    {
        memset(dp,-1,sizeof(dp));
        ans+=dfs(pos,0,0,true);
    }
    return ans;
}
int main()
{
    ll l,r;
    cin>>l>>r;
    cout<<fun(r)-fun(l-1)<<endl;
}

  

posted @ 2020-09-30 19:57  ~zcb  阅读(150)  评论(0编辑  收藏  举报