CF Beautiful numbers (數位dp + 數論)
阿新 • • 發佈:2018-12-09
題意:
求一個區間[l, r]內所有數字能被它每個數字整除的數的個數
思路:
一個數能被她的每一位數字整除,就是能被他們的最小公倍數整除,而lcm{1,2…9} = 2520,即這個數對2520取模後被最小公倍數整除,即使漂亮數
AC程式碼
#include <iostream>
#include <string.h>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <stdio.h>
#include <deque>
using namespace std;
#define LL long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define maxn 1005
#define eps 0.00000001
#define PI acos(-1.0)
#define M 1000000007
LL dp[30][2550][50];
int num[30];
map<int, int> MM;
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int lcm(int a, int b) {
return a/gcd(a, b) * b;
}
LL dfs(int pos, int m, int status, bool limit) {
if(!pos) return m % status == 0;
if(!limit && dp[pos][m][MM[status]]) return dp[pos][m][MM[status]];
int end = limit ? num[pos] : 9;
LL sum = 0; int a;
for (int i = 0; i <= end; i ++) {
if(!i) a = status;
else a = lcm(status, i);
sum += dfs(pos - 1, (m * 10 + i) % 2520, a, limit && (i == end));
}
return limit ? sum : dp[pos][m][MM[status]] = sum;
}
LL solve(LL n) {
num[0] = 0;
while(n) {
num[++ num[0]] = n % 10;
n /= 10;
}
return dfs(num[0], 0, 1, 1);
}
void init() {
memset(dp, 0, sizeof(dp));
MM[1] = 1; MM[2] = 2; MM[3] = 3; MM[4] = 4;
MM[5] = 5; MM[6] = 6; MM[7] = 7;
MM[8] = 8; MM[9] = 9;
MM[10] = 10; MM[12] = 11;
MM[14] = 12; MM[15] = 13;
MM[18] = 14; MM[20] = 15;
MM[21] = 16; MM[24] = 17;
MM[28] = 18; MM[30] = 19;
MM[35] = 20; MM[36] = 21;
MM[40] = 22; MM[42] = 23;
MM[45] = 24; MM[56] = 25;
MM[60] = 26; MM[63] = 27;
MM[70] = 28; MM[72] = 29;
MM[84] = 30; MM[90] = 31; MM[105] = 32; MM[120] = 33; MM[126] = 34;
MM[140] = 35; MM[168] = 36; MM[180] = 37;
MM[210] = 38; MM[252] = 39; MM[280] = 40;
MM[315] = 41; MM[360] = 42; MM[420] = 43; MM[504] = 44;
MM[630] = 45; MM[840] = 46; MM[1260] = 47;
MM[2520] = 48;
}
int main(int argc, const char * argv[]) {
LL T, l, r;
init();
scanf("%I64d", &T);
while(T --) {
scanf("%I64d %I64d", &l, &r);
printf("%I64d\n", solve(r) - solve(l - 1));
}
return 0;
}
}