Codeforces Beta Round #51---D. Beautiful numbers(數位dp, 巧妙),
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).
Sample test(s)
Input
1
1 9
Output
9
Input
1
12 15
Output
2
這題做法真的很精妙
如果一個數可以被它每一位上的數整除,那一定可以被那些數的LCM整除,最大的LCM是2520,因此那些數一定能被2520的因子某個整除
設dp[cur][rest][lcm]表示到第cur位,前面的數組成的數對2520模數為rest,之前的數的lcm為lcm的數的個數,直接這樣會超記憶體,所以第三維離散化一下
前面的數組成的數對2520模數後為什麼對答案沒有影響呢?
設這個數為2520 * k + b,對lcm模數,lcm是2520的一個因子,因此:
(2520 * k + b) % lcm = b % lcm
所以不影響
然後就是數位dp的事情了
顯然要用64位整數
/************************************************************************* > File Name: cf55d.cpp > Author: ALex > Mail: zchao1995@gmail.com > Created Time: 2015年02月23日 星期一 22時25分40秒 ************************************************************************/#include <map>#include <set>#include <queue>#include <stack>#include <vector>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const double pi = acos(-1);const int inf = 0x3f3f3f3f;const double eps = 1e-15;typedef long long LL;typedef pair <int, int> PLL;LL dp[33][2600][60];int LCM_ARR[60];int HASH[3000];int cnt;int bit[30];LL gcd (LL a, LL b){ return b ? gcd (b, a % b) : a;}LL LCM (LL a, LL b){ return a / gcd (a, b) * b;}LL dfs (int cur, int rest, int ind, bool flag, bool zero){ if (cur == -1) { if (zero) { return 0; } return (rest % LCM_ARR[ind] == 0); } if (!flag && ~dp[cur][rest][ind]) { return dp[cur][rest][ind]; } LL ans = 0; int end = flag ? bit[cur] : 9; for (int i = 0; i <= end; ++i) { if (zero && !i) { ans += dfs (cur - 1, 0, 0, flag && (i == end), 1); } else if (zero && i) { ans += dfs (cur - 1, i, HASH[i], flag && (i == end), 0); } else { if (i == 0) { ans += dfs (cur - 1, rest * 10 % 2520, ind, flag && (i == end), zero && (i == 0)); continue; } int lcm = LCM (LCM_ARR[ind], i); ans += dfs (cur - 1, (rest * 10 + i) % 2520, HASH[lcm], flag && (i == end), zero && (i == 0)); } } if (!flag) { dp[cur][rest][ind] = ans; } return ans;}LL calc (LL n){ int ret = 0; while (n) { bit[ret++] = n % 10; n /= 10; } return dfs (ret - 1, 0, 1, 1, 1);}int main (){ cnt = 0; memset (dp, -1, sizeof(dp)); for (int i = 1; i <= 2520; ++i) { if (2520 % i == 0) { LCM_ARR[++cnt] = i; HASH[i] = cnt; } } LL l, r; int t; scanf("%d", &t); while (t--) { cin >> l >> r; cout << calc (r) - calc (l - 1) << endl; } return 0;}