BZOJ-2818-Gcd(欧拉函数/Mobius反演)

Description

给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.

Input

一个整数N

Output

如题

Sample Input

4

Sample Output

4

HINT

hint

对于样例(2,2),(2,4),(3,3),(4,2)


1<=N<=10^7




首先欧拉函数:

小推一下公式:

Ans=prime(p)sigma(n,x=1)sigma(n,y=1)gcd(x,y)=p

       =prime(p)sigma(n/p,x=1)sigma(n/p,y=1)gcd(x,y)=1

显然,预先累加处理一下欧拉函数phi[i]表示i内(x,y)互质对数,然后枚举n的质因子p,累加就可以了,

但是注意此题答案无序,而预先处理出的是有序的,所以需要乘2再减掉重复的形如(3,3)的就好。



#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
#define bug cout<<"bug\n"
using namespace std;
const int MAXN = 1e7+7;
const int MAXM = 1e9+7;
long long phi[MAXN];
long long prime[MAXN];
int num_prime;
void get_euler(int n)
{
    num_prime=0;
    memset(phi,0,sizeof(phi));
    phi[1]=0;
    for(long long i=2; i<=n; ++i)
        if(!phi[i])
        {
            prime[num_prime++]=i;
            for(long long j=i; j<=n; j+=i)
            {
                if(!phi[j])
                    phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
        }
}
int main()
{
    long long n;
    //get_euler();
    scanf("%I64d",&n);
    {
        get_euler(n);
        long long ans=0;
        for(int i=2; i<=n; ++i)
            phi[i]+=phi[i-1];
        for(int i=0; i<num_prime; ++i)
            ans+=phi[n/prime[i]];
        ans=ans*2+num_prime;
        printf("%lld\n",ans);
        //cout<<ans<<endl;
    }
    return 0;
}



你可能感兴趣的:(C++,ACM)