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; }