题意:
找出L~R中所有的数字,数字和可以被每一位数字整除的总个数
思路:
1~9中,如果同时能被 比如1 3 5整除,那么一定能被最小公倍数15整除
建立HASH映射,反应在最小公倍数的情况下
for(int i=1;i<=MOD;i++)
{
if(MOD%i==0)
{
Hash[i]=cnt++;
}
}
对于当前数字,在表中对应个数。
之后DP【i】 【j】 【k】
i 表示数字长度, j 表示在Hash表中所在位置,K表示目前为止所有数字和
'
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm >
using namespace std;
typedef long long ll;
int digit[20];
const int MOD = 2520;
ll dp[20][50][2550];
int Hash[2550];
int gcd(int x,int y)
{
return x%y? gcd(y,x%y):y;
}
ll dfs(int len,int lcm,int have,int limit )
{
if(!len )
{
if(have%lcm==0)
return 1;
else
return 0;
}
if(!limit&&dp[len][ Hash[lcm] ][have]!=-1)
return dp[len][ Hash[lcm] ][have];
ll res=0;
int maxx=limit? digit[len]:9;
for(int i=0;i<=maxx;i++)
{
if(i==0)
res+=dfs(len-1,lcm,(have*10+i)%MOD ,limit&&i==maxx);
else
{
int lcm2=i*lcm/gcd(lcm,i);
res+=dfs(len-1,lcm2, (have*10+i)%MOD, limit&&i==maxx);
}
}
if(!limit)
dp[len][Hash[lcm]][have]=res;
return res;
}
ll solve(ll n)
{
int len=0;
while(n)
{
digit[++len]=n%10;
n/=10;
}
return dfs(len,1,0,1 );
}
int main()
{
ll n,cnt=0;
memset(dp,-1,sizeof(dp));
for(int i=1;i<=MOD;i++)
{
if(MOD%i==0)
{
Hash[i]=cnt++;
}
}
int T;
cin>>T;
while(T--)
{
ll l, r;
scanf("%lld%lld", &l, &r);
printf("%lld\n", solve(r) - solve(l-1));
}
}