数论-容斥原理 Cirno的完美算数教室
先暴力找出由 2, 9 组成的 <= R 的数字存到 P ,排序并去除满足 gcd(i, j) > 1 的一对 (i, j) 中的较大数得到 Pu(ique)
由容斥原理计算 [L, R] 含有 Pu 中至少一个约数的数的个数. 由于 Pu 中约数数量较大,二进制枚举子集法不可用,
所以写了个搜索来枚举。
当 R = 10^10 时, Pu = 681, 不太大,所以不会超时(如果这都超时那就脱鞋吧(划掉))。
1 #include <stdio.h> 2 #include <math.h> 3 #include <algorithm> 4 5 using namespace std; 6 7 typedef long long LL; 8 9 const int _N = 4000; 10 11 LL P[_N], Pu[_N]; 12 LL mx_bit, L, R, Pcnt, Pucnt, ans; 13 14 void _dfs(LL bit, LL v) 15 { 16 if (bit > mx_bit || v > R) return; 17 18 if (bit) P[++Pcnt] = v; 19 20 _dfs(bit+1, v*10 + 2), _dfs(bit+1, v*10 + 9); 21 return; 22 } 23 24 LL _gcd(LL t1, LL t2) { return t2 ? _gcd(t2, t1%t2) : t1; } 25 26 void _lalala(LL t1, LL t2, LL mul) 27 { 28 if (t1 == Pucnt+1) { 29 if (t2&1) 30 ans += R/mul - (L-1)/mul; 31 else if (t2) ans -= R/mul - (L-1)/mul; 32 return; 33 } 34 _lalala(t1+1, t2, mul); 35 mul = mul / _gcd(mul, Pu[t1]) * Pu[t1]; 36 if (mul <= R) _lalala(t1+1, t2+1, mul); 37 return; 38 } 39 40 int main() 41 { 42 LL i, j; 43 scanf("%lld%lld", &L, &R); 44 mx_bit = log(R+0.5)/log(10) + 1; 45 _dfs(0, 0); 46 sort(P+1, P+1+Pcnt); 47 for (i = 1; i <= Pcnt; ++i) { 48 if (!P[i]) continue; 49 Pu[++Pucnt] = P[i]; 50 for (j = i+1; j <= Pcnt; ++j) 51 if (P[j] && !(P[j] % P[i])) P[j] = 0; 52 } 53 // Pucnt = 681 and Pcnt = 2046 when R = 10^10 54 ans = 0; 55 _lalala(1, 0, 1); 56 printf("%lld\n", ans); 57 return 0; 58 }
题目:NKOJ4046
P4046Cirno的完美算数教室 | ||
|
问题描述
~Cirno发现了一种baka数,这种数呢~只含有2和9两种数字~~
现在Cirno想知道~一个区间中~~有多少个数能被baka数整除~
但是Cirno这么天才的妖精才不屑去数啦
只能依靠聪明的你咯。
输入格式
一行正整数L R
( 1 < L < R < 10^10)
输出格式
一个正整数,代表所求的答案
样例输入
1 100
样例输出
58