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

来源:互联网 发布:换热器软件 编辑:程序博客网 时间:2024/04/28 14:31

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;}



0 0