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