[bzoj2818]gcd

wscqwq發表於2024-08-22

https://darkbzoj.cc/problem/2818

https://vjudge.net.cn/contest/649469#problem/Q

給定整數N,求1≤x,y≤N且gcd(x,y)為素數的數對(x,y)有多少對.

N≤10^7

分析:線性篩出不大於N的所有素數,列舉gcd(x,y)(設為p),問題轉化為求(x,y)=p的個數。

設x=x'p, y=y'p,那麼有(x,y)=1且1≤x,y≤N/p。

轉化為求(x,y)=1且1≤x,y≤n的個數。

求(x,y)=1且1≤x,y≤N的個數:

若x≥y,對於x=1..n,有ϕ(x)個y滿足(x,y)=1

若x≤y,對於y=1..n,有ϕ(y)個x滿足(x,y)=1

若x=y,只有一種情況:(x=1, y=1)

所以答案為2(ϕ(1)+...+ϕ(n))-1

線性篩篩出尤拉函式、預處理字首和即可

#include<iostream>
#define int long long
using namespace std;
const int N=10000010;
int n,p[N/10],cnt,phi[N];
typedef long long ll;
ll ans;
bool st[N];
signed main(){
    #ifdef LOCAL
    freopen("1.txt","r",stdin);
    #endif
    #ifndef LOCAL
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    #endif
    cin>>n;
    phi[1]=1;
    for(int i=2,k;i<=n;++i){
        if(!st[i])st[i]=1,p[++cnt]=i,phi[i]=i-1;
        for(int j=1;(k=p[j]*i)<=n;++j){
            st[k]=1;
            if(i%p[j]==0){
                phi[k]=phi[i]*p[j];
                break;
            }
            else phi[k]=phi[i]*(p[j]-1);
        }
    }
    for(int i=2;i<=n;++i)phi[i]+=phi[i-1];
    for(int i=1;i<=cnt;++i){
        int nn=n/p[i];
        ans+=2*phi[nn]-1;
    }
    cout<<ans;
    return 0;
}