1. 程式人生 > >YY的GCD(莫比烏斯反演)

YY的GCD(莫比烏斯反演)

【題目描述】
神犇YY虐完數論後給傻×kAc出了一題
給定N,M,求1<=x<=N,1<=y<=Mgcd(x,y)為質數的(x,y)有多少對
kAc這種傻×必然不會了,於是向你來請教……
多組輸入T=10000N,M<=10000000

【輸入格式】
第一行一個整數T 表述資料組數
接下來T行,每行兩個正整數,表示N, M

【輸出格式】
T行,每行一個整數表示第i組資料的結果

【樣例輸入】
2
10 10
100 100

【樣例輸出】
30
2791

【思路】
貼一篇大佬的題解,太強了

BZOJ2820
本菜雞差不多照貓畫虎抄了一遍程式碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn=10000005;

bool vis[maxn];
int prim[maxn];
int mu[maxn];
ll g[maxn],sum[maxn];
int cnt;

void get_mu(int n){
    mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i]){
            prim[++cnt]=i;
            mu[i]=-1
; } for(int j=1;j<=cnt && prim[j]*i<=n;j++){ vis[prim[j]*i]=1; if(i%prim[j]==0) break; else mu[i*prim[j]]=-mu[i]; } } for(int j=1;j<=cnt;++j){ for(int i=1;i*prim[j]<=n;++i){ g[i*prim[j]]+=mu[i]; } } for
(int i=1;i<=n;++i) sum[i]=sum[i-1]+g[i]; } int main(){ get_mu(maxn-1); int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d%d",&n,&m); if(n>m) swap(n,m); ll ans=0; for(int L=1,R;L<=n;L=R+1){ R=min(n/(n/L),m/(m/L)); ans+=(sum[R]-sum[L-1])*(ll)(n/L)*(ll)(m/L); } printf("%lld\n",ans); } return 0; }