HSFZ_NOI_DIGIT_DP G 题解
G - Beautiful numbers
题目网址:https://vjudge.net/contest/243352#problem/G
题目来源:CF 55D http://codeforces.com/problemset/problem/55/D
time limit per test
memory limit per test
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
Please, do not use
Output
Output should contain
Examples
Input
1
1 9
Output
9
Input
1
12 15
Output
2
题目大意:对于一个正整数
数位
我们发现如果一个数能整除它的所有数位上的数,那么它一定能整除所有这些数位上的数的最小公倍数(性质
我们定义
由于性质
由f的定义,我们可以写出状态转移方程
在转移的过程中,需要注意前缀
然而,我们发现
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=20;
const int mod=2520;
int T,cur,a[mod+1];
ll l,r,f[20][mod+1][50];
vector<int>dim;
int gcd(int x,int y){return x%y?gcd(y,x%y):y;}
int lcm_(int x,int y){if(!y)return x;return x/gcd(x,y)*y;}
ll dfs(int x,int mode,int lcm,bool op)
{
if(!x)return mode%lcm==0?1:0;
if(!op&&f[x][mode][a[lcm]])return f[x][mode][a[lcm]];
int maxx=op?dim[x]:9;ll ret=0;
for(int i=0;i<=maxx;i++)ret+=dfs(x-1,(mode*10+i)%mod,lcm_(lcm,i),op&(i==maxx));
if(!op)f[x][mode][a[lcm]]=ret;
return ret;
}
ll solve(ll x)
{
dim.clear();
dim.push_back(-1);
ll t=x;
while(t)dim.push_back(t%10),t/=10;
return dfs(dim.size()-1,0,1,1);
}
main()
{
for(int i=1;i<=mod;i++)if(mod%i==0)a[i]=++cur;
scanf("%d",&T);
while(T--)scanf("%lld%lld",&l,&r),printf("%lld\n",solve(r)-solve(l-1));
return 0;
}