2820: YY的GCD

2820: YY的GCD

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 1693  Solved: 901
[Submit][Status][Discuss]

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

 

Source

 

/*
参考:http://blog.csdn.net/acdreamers/article/details/8542292
*/
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e7+5;
int T,n,m,tot,mu[N],g[N],sum[N],prime[N/3];
bool check[N];
void pre(){
    mu[1]=1;n=1e7+2;
    for(int i=2;i<=n;i++){
        if(!check[i]) prime[++tot]=i,mu[i]=-1,g[i]=1;
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            check[i*prime[j]]=1;
            if(!(i%prime[j])){mu[i*prime[j]]=0;g[i*prime[j]]=mu[i];break;}
            else mu[i*prime[j]]=-mu[i],g[i*prime[j]]=mu[i]-g[i];
        }
    }
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+g[i];
}
ll calc(int n,int m){
    if(n>m) swap(n,m);
    ll ans=0;int pos=0;
    for(int i=1;i<=n;i=pos+1){
        pos=min(n/(n/i),m/(m/i));
        ans+=(ll)(n/i)*(m/i)*(sum[pos]-sum[i-1]);
    }
    return ans;
}
int main(){
    pre();
    for(scanf("%d",&T);T--;){
        scanf("%d%d",&n,&m);
        printf("%lld\n",calc(n,m));
    }
    return 0;
}

 

posted @ 2017-02-16 22:21  神犇(shenben)  阅读(668)  评论(0编辑  收藏  举报