我们可以枚举每一个p在[2, sqrt(n)]里,然后就是在[p + 1, n / p]中找有多少个数和p互质了。
标准容斥,先算出[1, n / p]中有多少个和p互质,这个是不能用欧拉定理做的,需要把p质因数分解,然后dfs
求解元素X在区间[1, up]中,有多少个数和X互质。(容斥)
思路:把X质因数分解,多了的不要。12 = 2 * 3。然后有个明显的道理就是如果是2的倍数的话,那么就一定不会与12互质,所以需要减去2的倍数,减去3的倍数,再加上6的倍数。容斥的思路好想,但是不怎么好写。所以结果是总数量up – 不互质的个数。
预处理;his[val][]表示元素val拥有的质因子,Size[val]表示有多少个。记得1是不做任何处理的。就是Size[1] = 0。Dfs的cur表示下一次从哪里开始,不往回枚举,就是任意k个值。
int calc(int up, int cur, int number, int tobuild, int flag) { //一开始flag是0。0表示加,1减
int ans = 0;
for (int i = cur; i <= Size[number]; ++i) {
if (flag == 0) {
ans += up / (his[number][i] * tobuild);
} else ans -= up / (his[number][i] * tobuild);
ans += calc(up, i + 1, number, his[number][i] * tobuild, !flag);
}
return ans;
}
计算12在[1, 24]就是24 - calc(24, 1, 12, 1, 0)。tobuild是选择k个质因数后生成的数字。
#include #include #include #include #include #include #define IOS ios::sync_with_stdio(false)using namespace std;#define inf (0x3f3f3f3f)typedef long long int LL;#include #include #include #include #include
View Code