【题解】 P4127 [AHOI2009]同类分布

\(Description:\)

给出两个数a,b,求出\([a,b]\)中各位数字之和能整除原数的数的个数。

$Sample $ \(Input:\)

10 19

\(Sample\) \(Output:\)

3

\(Solution:\)

设计状态 \(f[len][sum][res]\) 表示倒数还有 \(i\) 位要做,当前的和是 \(sum\) ,摸掉模数后剩下的数是 \(res\),

那么我们直接暴力枚举模数,\(len=0\) 最后判断一下是否 \(sum=mod\) \(\&\&\) \(res=0\) 这个时候可以吧答案返回为 \(1\)

那么再套个板子就。。。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a,b;
const int N=20+1,M=200+1;
int f[N][M][M],digit[N];
inline int dfs(int len,int sum,int res,int p,bool limit){
	if(len==0) {
		if(res==0) return (sum==p)?1:0;// 答案的判断,以为这样写可以加速,实际上变慢了。。。
		return 0;
	}
	if(!limit && f[len][sum][res]!=-1) return f[len][sum][res];
	int ret=0,up_bound=(limit)?digit[len]:9;
	for(int i=0;i<=up_bound;++i)
		ret+=dfs(len-1,sum+i,(res*10+i)%p,p,limit&&i==up_bound);
	return f[len][sum][res]=ret;
}
inline int solve(int n){
	int cnt=0,ret=0;
	while(n){
		digit[++cnt]=n%10;
		n/=10;
	}
	for(int p=1;p<=9*cnt;++p){//最多枚举到各位都是9
		memset(f,-1,sizeof(f));
		ret+=dfs(cnt,0,0,p,true);
	}
	return ret;
}
signed main(){
	scanf("%lld%lld",&a,&b);
	printf("%lld\n",solve(b)-solve(a-1));
	return 0;
}
posted @ 2019-04-15 18:00  章鱼那个哥  阅读(137)  评论(0编辑  收藏  举报