您的位置:首页 > 其它

SPOJ 7001 VLATTICE - Visible Lattice Points(莫比乌斯反演)

2015-09-08 20:50 288 查看
题目链接:http://www.spoj.com/problems/VLATTICE/

题意:求gcd(a, b, c) = 1 a,b,c <=N 的对数。

思路:我们令函数g(x)为gcd(a, b, c) = x的对数,那么这题就是要求g(1)。我们令f(x)为x | gcd(a, b, c)的对数,显然f(n) = sigma(n | d, g(d)) 。f(d) = (n/d) * (n/d) * (n/d),那么我们就可以用莫比乌斯反演公式了, g(n) = sigma(n | d, mu(d/n)f(d)) g(1) = mu(d)f(d) = mu(d)*(n/d)*(n/d)*(n/d)。考虑1位为0,2位为0的情况。

莫比乌斯反演的两种形式:

g(n) = sigma(d | n, f(d)) f(n) = sigma(d | n, mu(d) * g(n/d))

g(n) = sigma(n | d, f(d)) f(n) = sigma(n | d, mu(d / n) * g(d))

code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAXN = 1000005;
bool check[MAXN];
int primes[MAXN];
int mu[MAXN];

void moblus()
{
memset(check, false, sizeof(check));
mu[1] = 1;
int cnt = 0;
for (int i = 2; i < MAXN; ++i) {
if (!check[i]) {
primes[cnt++] = i;
mu[i] = -1;
}
for (int j = 0; j < cnt; ++j) {
if (i * primes[j] > MAXN) break;
check[i * primes[j]] = true;
if (i % primes[j] == 0) {
mu[i * primes[j]] = 0;
break;
} else {
mu[i * primes[j]] = -mu[i];
}
}
}
}

int main()
{
moblus();
int nCase;
scanf("%d", &nCase);
while (nCase--) {
int n;
scanf("%d", &n);
LL ans = 3;        // 001 010 100
for (int i = 1; i <= n; ++i) {
ans += (LL)mu[i] * (n / i) * (n / i) * (n / i + 3);
}
printf("%lld\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: