NKOJ 3957 (BZOJ 2820)YY的GCD (莫比烏斯反演+線性篩)

P3957YY的GCD

問題描述

神犇YY虐完數論後給傻×kAc出了一題
給定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)爲質數的(x, y)有多少對
kAc這種傻×必然不會了,於是向你來請教……

輸入格式

第一行一個整數T 表述數據組數

接下來T行,每行兩個正整數,表示N, M

輸出格式

T行,每行一個整數表示第i組數據的結果

樣例輸入

2
10 10
100 100

樣例輸出

30
2791

提示

T = 10000

N, M <= 10000000


顯然Ans=pmin(n,m)i=1nj=1m[gcd(i,j)==p]p

f(p)=i=1nj=1m[gcd(i,j)==p],F(p)=i=1nj=1m[p|gcd(i,j)]

N=min(n,m)F(p)=p|kNf(k)=npmp

f(p)=p|kNμ(kp)F(k)=p|kNμ(kp)nkmk

Ans=pNf(p)=pNp|kNμ(kp)nkmk

如果是單組詢問,到這裏已經可以了,但本題有多組詢問,因此
Ans=k=1Nnkmkp|kμ(kp)p

後面的部分可以直接枚舉質數再枚舉倍數預處理,複雜度接近O(n)
但顯然可以線性篩處理,令其爲g[i] ,當p[j]|i 時,g[ip[j]]=μ(i) ,否則g[ip[j]]=mu[i]g[i]
然後分塊處理即可,複雜度O(n+Tn)

代碼:

#include<stdio.h>
#include<algorithm>
#define N 10000005
#define ll long long
using namespace std;
ll T,P[N],tot,mu[N],g[N];
bool mark[N];
void EU()
{
    ll i,j;mu[1]=1;g[1]=0;
    for(i=2;i<N;i++)
    {
        if(!mark[i])P[++tot]=i,mu[i]=-1,g[i]=1;
        for(j=1;j<=tot&&i*P[j]<N;j++)
        if(i%P[j])mu[i*P[j]]=-mu[i],g[i*P[j]]=mu[i]-g[i],mark[i*P[j]]=1;
        else {mu[i*P[j]]=0;g[i*P[j]]=mu[i];mark[i*P[j]]=1;break;}
    }
    for(i=2;i<N;i++)g[i]+=g[i-1];
}
int main()
{
    ll n,m,i,j,ans;
    scanf("%lld",&T);EU();
    while(T--)
    {
        scanf("%lld%lld",&n,&m);ans=0;
        for(i=1;i<=n&&i<=m;i=j+1)
        {
            j=min(n/(n/i),m/(m/i));
            ans+=(n/i)*(m/i)*(g[j]-g[i-1]);
        }
        printf("%lld\n",ans);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章