BZOJ 2818: Gcd(尤拉函式)
阿新 • • 發佈:2019-02-07
Description
給定整數N,求1<=x,y<=N且Gcd(x,y)為素數的
數對(x,y)有多少對.
Input
一個整數N
Output
如題
Sample Input
4Sample Output
4HINT
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)特解,減一)。
程式碼:
#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; }