BZOJ 2818: 欧拉筛法求gcd(x,y)==k(k为质数)

来源:互联网 发布:好用的鼠标 知乎 编辑:程序博客网 时间:2024/04/28 15:24

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(px,py)==p;
有GCD(x,y)==1,在1-n/p的情况数。即1-n/p的欧拉和。p为质数。
所以直接模板套上筛。。就可以了。。
注意(2,4)(4,2)是两种情况要*2.。但是(2,2)这种有不是,又要剪掉。。

#include<bits/stdc++.h>using namespace std;#define LL long longconst int mod=1000000007;const int maxn=10000005;bool check[maxn];          //用于打表记录的中间量LL sumPhi[maxn];           //前i个的欧拉函数和int cnt,phi[maxn],prime[maxn];  //素数个数,欧拉表,素数表//素数表是第几个素数是什么,欧拉表是i的欧拉是phi[i];void init(int n){               //素数+欧拉表    phi[1]=1;    cnt=0;    for(int i=2;i<=n;i++){        if(!check[i]){            phi[i]=i-1;            prime[cnt++]=i;        }        for(int j=0;j<cnt;j++){            if(i*prime[j]>n)break;            check[i*prime[j]]=true;            if(i%prime[j]==0){                phi[i*prime[j]]=phi[i]*prime[j];                break;            }            else{                phi[i*prime[j]]=phi[i]*(prime[j]-1);            }        }    }    sumPhi[0]=0;    for(int i=1;i<=n;i++) sumPhi[i]=(sumPhi[i-1]+phi[i]);}int main(){    int n;    while(cin>>n){        LL ans=0;        init(n);        for(int i=0;i<cnt;i++){            ans+=sumPhi[n/prime[i]];        }        cout<<2*ans-cnt<<endl;    }    return 0;}
0 0
原创粉丝点击