hdu5179 beautiful number

因为递推版本的数位dp容易错 (主要还是我不会写),所以选择了记忆化搜索的方式。

详见代码。

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int digit[100];/*digit[]:存储每个数字*/
int dp[20][20];/*记忆化数组*/
int dfs(int step/*当前的数位编号*/,int pre/*上一个数字*/,bool zero/*是否有前导零*/,bool lmt/*是否有数字的上限*/) 
{
	if(!step) return 1;/*找到一个可行解*/
	if(dp[step][pre] && !zero && !lmt) return dp[step][pre];/*已经搜过,无需再次搜索(记忆化)*/
	int high=(lmt ? digit[step] :9)/*可以循环到的最高位*/,ans=0;
	for(int i=0;i<=high;i++)
		if(zero || (i && pre%i==0 && pre>=i))/*当前这个数字可以*/
			ans+=dfs(step-1,i,zero && i==0,lmt && i==digit[step]);
	if(!lmt && !zero) dp[step][pre]=ans;/*记忆化*/
	return ans;
}
int solve(int n)/*回答每个询问*/
{
	int len=0;
	while(n)
	{
		digit[++len]=n%10;
		n/=10;
	}/*存储每一位(倒序)*/
	return dfs(len,-1,true,true);/*由于倒序存储(见上面的循环),需要从len枚举到1*/
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
	    memset(dp,0,sizeof(dp));
		int l,r;
		scanf("%d %d",&l,&r);
		printf("%d\n",solve(r)-solve(l-1));
	}
	return 0;
}
posted @ 2020-02-08 17:43  zzt1208  阅读(121)  评论(0编辑  收藏  举报