Beautiful numbers CodeForces - 55D(数位dp)

topic

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

The meaning of problems

Looking beautiful l r on the number of interval number, are defined beautiful number divisible by the number of values ​​for each digit of the number is the number of beauty.

Thinking

It can be transformed into a beautiful number: the number can be, its composition divisible by the least common multiple of each digit. The set number y, there are n bits (n <= 19), a bit x1, one hundred to x2, and so on, are all set to the least common multiple LCM xi, beautiful condition number is converted to y% lcm = 0.
Digit number using dp, dp [pos] [sum ] [lcm] represents the position pos, pos bits of the former sum, the composition of the least common multiple lcm case, the number of array beautiful meet several criteria.
Because a large sum, but in fact the least common multiple of 1-9 was 2520, so we continue to take the remainder 2520 pairs sum, without prejudice to whether the results can be divisible. In addition, all digits of the least common multiple lcm in fact no 2520, hash keep it (the least common multiple is in line with some combination of numbers 1 to 9 to different cont, like distinguished, size cont how much value there is no comparison significance).
dfs outlet to a representative of a certain specific number, if the number corresponding to the sum% lcm contribution is 0 plus 1, was not 0;
DP stored memo while, if it is known can be directly used when the current position is not restricted when space is limited enumeration of smaller, previously stored is not equal to dp, dp storage is no limit in the state, in large samples, without limitation, the number appears much larger than the event of restrictions.

#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
ll dp[20][2521][50];
int hash[2521];
int dig[20];
int gcd(int a, int b){
	return b == 0 ? a:gcd(b, a%b);
}
int LCM(int a, int b){
	if(a == 0||b == 0)
		return a+b;
	return a*b/ gcd(a, b);
}
ll dfs(int pos, int sum, int lcm, int limit){
	if(pos == -1) return sum%lcm == 0?1:0;
	if(!limit && dp[pos][sum][hash[lcm]] != -1) return dp[pos][sum][hash[lcm]];
	int up = limit ? dig[pos]:9;
	ll ans = 0;
	int nsum = 0; int nlcm = 0;
	for(int i = 0; i <= up; i++){
		nsum = (sum*10+i)%2520;
		nlcm = LCM(i, lcm);
		ans += dfs(pos-1,nsum, nlcm, limit && i == up);
	}
	if(!limit) dp[pos][sum][hash[lcm]] = ans;
	return ans;
}
ll slove(ll x){
	int pos = 0;
	while(x){
		dig[pos++] = x%10;
		x /= 10;
	}
	ll ans = dfs(pos-1, 0, 1, 1);
	return ans;
}
int main(){
	int t, i;
	scanf("%d", &t);
	memset(dp, -1, sizeof(dp));
	int cont = 0;
	for(i = 1; i*i < 2520; i++){
		if(2520 % i == 0){
			hash[i] = cont++;
			hash[2520/i] = cont++;
		}
	}
	ll r,l;
	while(t--){
		scanf("%I64d %I64d", &l, &r);
		printf("%I64d\n", slove(r) - slove(l-1));
	}
	return 0;
}
Published 52 original articles · won praise 2 · Views 864

Guess you like

Origin blog.csdn.net/qq_44714572/article/details/103206308