[CF55D]Beautiful Number 题解

数位dp进阶题。

如果一个数能被它的所有数位整除,那么他一定可以被那些数位的$LCM$整除。
发现$1-9$的$LCM$是$2520$,所以这些数位的$LCM$一定是$2520$的约数,正确性显然。
于是就有:如果这个数$mod\ 2520$能被数位的$LCM$整除,那么这个数同样也能。
所以设计状态为:
$dp[i][j][k]$为还剩i位没填,之前几位形成的数$mod\ 2520 = j$,之前所有数位$LCM$为$k$的数的个数。

转移就直接转移就行了。同时发现空间会爆炸,压缩一下$k$就可以了。

计算请参照我的另一篇博客:SCOI2009 windy数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
* @Author: Mingyu Li
* @Date: 2019-03-10T10:20:16+08:00
* @Email: class11limingyu@126.com
* @Filename: CF55D.cpp
* @Last modified by: Mingyu Li
* @Last modified time: 2019-03-10T13:12:06+08:00
*/

#include <bits/stdc++.h>
#define tpname typename
#pragma GCC optimize("O2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#define Go(i , x , y) for(register int i = x; i <= y; i++)
#define God(i , y , x) for(register int i = y; i >= x; i--)
typedef long long LL;
typedef long double ld;
typedef unsigned long long ULL;
template < tpname T > void sc(T& t) {
char c = getchar(); T x = 1; t = 0; while(!isdigit(c)) {if(c == '-') x = -1; c = getchar();}
while(isdigit(c)) t = t * 10 + c - '0' , c = getchar();t *= x;
}
template < tpname T , tpname... Args > void sc(T& t , Args&... args) {sc(t); sc(args...);}
template < tpname T > T mul(T x , T y , T _) {
x %= _,y %= _; return ((x * y - (T)(((ld)x * y + 0.5) / _) * _) % _ + _) % _;
}


LL t;
LL l , r , m , d[25];

LL dp[20][2525][55];

LL num[2525];
LL ca1l(LL x) {
return x < 2520 ? x : x - (x / 2520) * 2520;
}
// dp[x][y][z]: 还剩x位 前面数%2520 = y 前面所有数lcm=z
LL lcm(LL x , LL y) {
if(x < y) std::swap(x,y);
return !y ? x : x/std::__gcd(x,y)*y;
}
LL F(LL x , LL y , LL z) {
if(dp[x][y][num[z]] != -1) return dp[x][y][num[z]];

if(x == 0) return dp[x][y][num[z]] = (z == 0 || (y / z) * z == y) ? 1 : 0;
LL ans = 0;
Go(q , 0 , 9) {
ans += F(x-1 , ca1l((y * 10 + q)) , lcm(z , q));
}
return dp[x][y][num[z]] = ans;
}

LL cal(LL x) {
m = 0;
while(x) {
d[m++] = x%10; x /= 10;
}

LL ans = 0;
Go(i , 1 , m-1) {
Go(j , 1 , 9) ans += F(i-1 , j , j);
}

LL times=0 , lc=1;
God(i , m-1 , 0) {
Go(j , (i == m-1) ? 1 : 0 , d[i]-1) {
ans += F(i ,ca1l(times * 10 + j) , lcm(lc , j));
}
times = ca1l(times * 10 + d[i]);
lc = lcm(lc , d[i]);
}
return ans;
}

int main() {
memset(dp , -1 , sizeof(dp));
std::cin >> t;
num[0] = 1;
int cnt = 1;
Go(i , 1 , 2520) if(2520 % i == 0) num[i] = ++cnt;
while(t--) {
std::cin >> l >> r;
std::cout << cal(r+1) - cal(l) << std::endl;
}
return 0;
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×