GCD 莫比乌斯反演 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的 数对(x,y)有多少对.

/**
题目:GCD
链接:https://vjudge.net/contest/178455#problem/E
题意:给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.

1<=N<=10^7

思路:
定义:
f(n)表示gcd(x,y)==n的对数。
F(n)表示n|gcd(x,y)的对数。

枚举n以内的素数p;

f(p) = sigma(mu[d/p]*F(d)) (p|d)

F(d) = (n/d)*(n/d);     N/10*sqrt(N)复杂度。

*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
#define ms(x,y) memset(x,y,sizeof x)
typedef pair<int, int> P;
const LL INF = 1e10;
const int mod = 1e9 + 7;
const int maxn = 1e7 + 100;
int prime[maxn], tot, not_prime[maxn];
int mu[maxn], sum[maxn];
void init()
{
    mu[1] = 1;
    tot = 0;
    for(int i = 2; i < maxn; i++){
        if(!not_prime[i]){
            prime[++tot] = i;
            mu[i] = -1;
        }
        for(int j = 1; prime[j]*i<maxn; j++){
            not_prime[prime[j]*i] = 1;
            if(i%prime[j]==0){
                mu[prime[j]*i] = 0;
                break;
            }
            mu[prime[j]*i] = -mu[i];
        }
    }
    for(int i = 1; i < maxn; i++) sum[i] = sum[i-1]+mu[i];
}
LL solve(int n)///x在[1,n], y在[1,n],z在[1,n] gcd(x,y,z)=1的对数。
{
    LL ans = 0;
    int last;
    for(int i = 1; i <= n; i=last+1){
        last = n/(n/i);
        ans += (LL)(sum[last]-sum[i-1])*(n/i)*(n/i);
    }
    return ans;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int T;
    int n;
    init();
    while(scanf("%d",&n)==1)
    {
        LL ans = 0;
        for(int i = 1; i <= tot&&prime[i]<=n; i++){
            ans += solve(n/prime[i]);
            //cout<<"prime = "<<prime[i]<<endl;
            //cout<<"ans = "<<ans<<endl;
        }
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xiaochaoqun/p/7363215.html