[洛谷P2257] YY的GCD

Description###

神犇YY虐完数论后给傻×kAc出了一题

给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对

kAc这种傻×必然不会了,于是向你来请教……

多组输入

Input###

第一行一个整数T 表述数据组数

接下来T行,每行两个正整数,表示N, M

Output###

T行,每行一个整数表示第i组数据的结果

Sample Input###

2
10 10
100 100

Sample Output###

30
2791

HINT###

T = 10000
N, M <= 10000000


想法##

Orz PoPoQQQ大神……
若枚举每个质数 \(p\)

\[\begin{equation*} \begin{aligned} ans&= \sum\limits_p \sum\limits_{p|k} \mu(\frac{k}{p}) F(k) \\ &= \sum\limits_p \sum\limits_{d=1}^{\frac{min(n,m)}{p}} \mu(d) \lfloor \frac{n}{dp} \rfloor \lfloor \frac{m}{dp} \rfloor \end{aligned} \end{equation*} \]

\(T=dp\)

\[ans=\sum\limits_{T=2}^{min(n,m)} \lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor \sum\limits_{p|T 且p为质数} \mu(\frac{T}{p}) \]

预处理计算每个数 \(T\)\(\sum\limits_{p|T 且p为质数} \mu(\frac{T}{p})\) 及其前缀和
用每个质数把自己的倍数筛一遍就行了。


代码##

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

typedef long long ll;
const int N = 10000005;

int mu[N];
ll sum[N];
int prime[N],pnum,p[N];
int getmu(){
    mu[1]=1;
    for(int i=2;i<N;i++) p[i]=1;
    for(int i=2;i<N;i++){
        if(p[i]) {
            prime[pnum++]=i;
            mu[i]=-1;        
        }
        for(int j=0;j<pnum && (ll)prime[j]*i<N;j++){
            p[i*prime[j]]=0;
            if(i%prime[j]==0) {
                mu[i*prime[j]]=0;
                break;
            }
            mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=0;i<pnum;i++)
        for(int j=1;(ll)j*prime[i]<N;j++)
            sum[j*prime[i]]+=mu[j];
    sum[1]=0;
    for(int i=2;i<N;i++) sum[i]+=sum[i-1];
}

int n,m,T;

int main()
{
    getmu();
    scanf("%d",&T);
    
    ll ans;
    while(T--){
        scanf("%d%d",&n,&m);
        ans=0;
        for(int l=2,r;l<=min(n,m);l=r+1){
            r=min(n/(n/l),m/(m/l));
            ans+=(sum[r]-sum[l-1])*(n/l)*(m/l);
        }
        printf("%lld\n",ans);
    }
    
    return 0;    
}
posted @ 2018-03-04 12:10  秋千旁的蜂蝶~  阅读(177)  评论(0编辑  收藏  举报