首页 > 代码库 > YY的GCD(bzoj 2820)

YY的GCD(bzoj 2820)

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

 

盗图来自:http://blog.csdn.net/z690933166/article/details/11896565

技术分享

#include<cstdio>
#include<iostream>
#define N 10000010
#define lon long long
using namespace std;
int mul[N],prime[N],num,g[N],sum[N],f[N];
lon ans,n,m;
void get_prime(){
    mul[1]=1;
    for(int i=2;i<N;i++){
        if(!f[i]) prime[++num]=i,mul[i]=-1,g[i]=1;
        for(int j=1;j<=num&&i*prime[j]<N;j++){
            f[i*prime[j]]=1;
            if(i%prime[j]) mul[i*prime[j]]=-mul[i],g[i*prime[j]]=mul[i]-g[i];
            else {
                mul[i*prime[j]]=0;g[i*prime[j]]=mul[i];break;
            }
        }
    }
    for(int i=1;i<N;i++) sum[i]=sum[i-1]+g[i];
}
int main(){
    get_prime();
    int T;scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&n,&m);
        if(n>m) swap(n,m);
        ans=0;
        for(lon i=1,last=0;i<=n;i=last+1){
            last=min(n/(n/i),m/(m/i));
            ans+=(n/i)*(m/i)*(sum[last]-sum[i-1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

YY的GCD(bzoj 2820)