题目链接:CodeForces - 55D Beautiful numbers
Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with this and just count the quantity of beautiful numbers in given ranges.
Input
The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two natural numbers li and ri (1 ≤ li ≤ ri ≤ 9 ·1018).
Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cin (also you may use %I64d).
Output
Output should contain t numbers — answers to the queries, one number per line — quantities of beautiful numbers in given intervals (from li to ri, inclusively).
Examples
Input
1
1 9
Output
9
Input
1
12 15
Output
2
题意:
定义一个数能被自身所有数位上的非零数整除的数为漂亮数,求 [L, R] 范围内有多少漂亮数?
分析:
首先,一个数能被自身所有数位上的非零数整除,就是一个数能被自身所有数位上的非零数的最小公倍数(LCM)整除,可以发现1~9的LCM为2520,所以每次可以令( num*10+i ) % 2520。
所以可以dp需要记录当前的 最小公倍数LCM 和 num%2520,即 dp[pos][lcm][num]
但是这样会占用很多内存,实际上1~9的最小公倍数LCM只有48个,那么就可以离散化处理(建立映射),从而减少内存占用。
以下代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<climits>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
int a[30],mp[2600];
LL dp[30][50][2600];
int LCM(int a,int b)
{
int x=a,y=b,z;
while(y)
{
z=x%y;
x=y;
y=z;
}
return a/x*b;
}
LL dfs(int pos,int lcm,int num,bool limit)
{
if(pos<0)
{
if(num%lcm==0)
return 1;
else
return 0;
}
if(!limit&&dp[pos][mp[lcm]][num]!=-1)
return dp[pos][mp[lcm]][num];
int up=limit?a[pos]:9;
LL sum=0;
for(int i=0;i<=up;i++)
{
if(i==0)
sum+=dfs(pos-1,lcm,(num*10+i)%2520,limit&&i==up);
else
sum+=dfs(pos-1,LCM(i,lcm),(num*10+i)%2520,limit&&i==up);
}
if(!limit)
dp[pos][mp[lcm]][num]=sum;
return sum;
}
LL solve(LL x)
{
int len=0;
while(x)
{
a[len++]=x%10;
x/=10;
}
return dfs(len-1,1,0,true);
}
int main()
{
int cnt=0;
for(int i=1;i<=2520;i++)
{
if(2520%i==0)
mp[i]=cnt++; //离散化
}
memset(dp,-1,sizeof(dp));
int T;
scanf("%d",&T);
while(T--)
{
LL L,R;
scanf("%I64d %I64d",&L,&R);
printf("%I64d\n",solve(R)-solve(L-1));
}
return 0;
}