【spoj7001】莫比乌斯反演

来源:互联网 发布:近年来的交通事故数据 编辑:程序博客网 时间:2024/05/16 05:51

题目:给出n,求出有多少小于n的三元组(自然数),使得gcd(x, y, z)为1, 即从三维空间(0, 0, 0) 可以看到的点数。

莫比乌斯反演两种形式



证明:

此题用的是第二种,设f(m)为m | gcd(x, y, z)个数,g(m)为gcd(x, y, z) = m 的个数。因为f(x) = (n/x) ^ 3, 且f(x) = sigma{ x|d, g(d) }, 所以g(x) = sigma{ x|d, mu(d/x) * f(d) }. 算出g(1)即可。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <string>#define Rep(i, x, y) for (int i = x; i <= y; i ++)using namespace std;typedef long long LL;const int N = 1000005;int n, pri[N], tot, mu[N], T;bool c[N];LL ans;void Pre() {mu[1] = 1;Rep(i, 2, N-5) {if (!c[i]) pri[++ tot] = i, mu[i] = -1;Rep(j, 1, tot) {if (i * pri[j] > N-5) break ;c[i*pri[j]] = 1;if (i % pri[j] == 0) {mu[i*pri[j]] = 0;break ;}mu[pri[j]*i] = -mu[i];}}}int main(){cin >> T;Pre();while (T --) {scanf ("%d", &n), ans = 3;for (int i = 1; i <= n; i ++) ans += LL(mu[i]) * (n/i) * (n/i) * (n/i+3);printf("%lld\n", ans);}    return 0;}


0 0