1. 程式人生 > >CF Beautiful numbers (數位dp + 數論)

CF Beautiful numbers (數位dp + 數論)

題意:

求一個區間[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; } }