BZOJ 2818: Gcd(欧拉函数)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2818

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


题目思路:

假设gcd(x,y) = s;

则s是一个素数,且s*a=x;s*b=y;

则a,b互质,gcd(a,b)=1;

我们枚举素数s,求出所有的y<=n的x的个数,则预处理一个前缀和代表所有小于等于t的欧拉函数值的和sum[t]。

则对于任意一个素数满足条件的个数有sum[n/prime[i]]*2-1(有序对交换,所以乘2,舍去(1,1)特解,减一)。


欧拉函数模板可看:https://blog.csdn.net/baodream/article/details/80542418


代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<map>

using namespace std;

#define FOU(i,x,y) for(int i=x;i<=y;i++)
#define FOD(i,x,y) for(int i=x;i>=y;i--)
#define MEM(aA,val) memset(a,val,sizeof(a))
#define PI acos(-1.0)

const double EXP = 1e-9;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const ll MINF = 0x3f3f3f3f3f3f3f3f;
const double DINF = 0xffffffffffff;

const int N = 1e7+5;

int sum[N];
int phi[N],prime[N];
int tot;  //计数,表示prime[N]中有多少质数
void Euler(int n){  ////筛出所有小于等于n的欧拉函数值和素数
    memset(phi,0,sizeof(phi));
    tot=0,phi[1]=1;
    for(int i=2;i<=n;i++){
        if(!phi[i]){
            phi[i] = i-1;
            prime[tot++]=i;
        }
        for(int j=0;j<tot&&1ll*i*prime[j]<=n;j++){
            if(i%prime[j]!=0) phi[i*prime[j]] = phi[i] * (prime[j]-1);
            else{
                phi[i*prime[j]] = phi[i]*prime[j];
                break;
            }
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    std::ios::sync_with_stdio(false);
    int n;
    while(cin>>n)
    {
        Euler(n);
        sum[0]=0;
        for(int i=1;i<=n;i++)
            sum[i] = sum[i-1]+phi[i];
        int ans=0;
        for(int i=0;i<tot;i++)
            ans+=sum[n/prime[i]]*2-1;
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/baodream/article/details/80542470
今日推荐