4127 同类分布
人生的第一道紫题
练数位DP来的
题目很简单,题意也很好理解,往往很nb的题都是这个样子
对于一个区间的[l,r],每一个数x都需要计算各位,然后进行比较,O(n2),如果用暴力肯定就炸了
这个数位最大是18,每个位的共有9个数,所以各位数之和最大只是9*18=162
枚举这个和sum,然后统计可以被sum整除且数位是sum的数
设f[i][j][k]表示当前枚举到了第i位,目前这个数数位和是j,对sum取模是k
最后的答案j=sum并且k=0
一般我们求的是<n的个数所以答案为dfs®-dfs(l-1)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
ll l,r;
ll f[20][200][200];
int len,a[20],mod;
ll seartch(int i,int j,ll x,int l)
{
if(i>len&&j==0) return 0;
if(i>len) return x==0&&j==mod?1:0;
if(l==0&&f[i][j][x]!=-1) return f[i][j][x];
ll ret=0;
int res=l? a[len-i+1] : 9;
for(int a=0;a<=res;a++)
ret+=seartch(i+1,j+a,(10ll*x+a)%mod,a==res&&l);
return l?ret:f[i][j][x]=ret;
}
ll dfs(ll x)
{
len=0;
while(x) a[++len]=x%10,x/=10;
ll ret=0;
for(mod=1;mod<=9*len;mod++)//枚举模数
{
memset(f,-1,sizeof f);
ret+=seartch(1,0,0,1);
}
return ret;
}
int main()
{
scanf("%lld%lld",&l,&r);
printf("%lld\n",dfs(r)-dfs(l-1));
return 0;
}