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;
}
浙公网安备 33010602011771号