bzoj2820 YY的GCD

YY的GCD

Time Limit: 10 Sec Memory Limit: 512 MB

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


$$ans = \sum_{D=1}^N \sum_{p \mid\ D}\mu(\frac{D}{P}) \lfloor \frac{N}{D} \rfloor \lfloor \frac{M}{D} \rfloor$$ 然后讨论将里面的那个线筛即可。

```c++

include<bits/stdc++.h>

using namespace std;
const int maxn = 10000000 + 5;
int N, M, tot, mu[maxn], s[maxn], prime[maxn];
long long ans;
bool not_prime[maxn];

inline void prepare(){
mu[1] = 1; int lim = 10000000;
for(int i = 2; i <= lim; ++i){
if(!not_prime[i]){prime[++tot] = i; mu[i] = -1; s[i] = 1;}
for(int j = 1; prime[j] * i <= lim; ++j){
int now = i * prime[j]; not_prime[now] = true;
if(i % prime[j] == 0){mu[now] = 0; s[now] = mu[i]; break;}
mu[now] = -mu[i]; s[now] = mu[i] - s[i];
}
}
//for(int i = 1; i <= 30; ++i) printf("s[%d] = %d\n", i, s[i]);
for(int i = 2; i <= lim; ++i) s[i] += s[i - 1];
}

int main()
{
//freopen("lpl.in", "r", stdin);
prepare();
int T; scanf("%d", &T);
while(T--){
scanf("%d%d", &N, &M);
ans = 0; if(N > M) swap(N, M); int last;
for(int D = 1; D <= N; D = last + 1){
last = min(N / (N / D), M / (M / D));
ans += (long long)(s[last] - s[D - 1]) * (N / D) * (M / D);
}
printf("%lld\n", ans);
}
return 0;
}

posted @ 2018-09-29 17:21  沛霖  阅读(109)  评论(0编辑  收藏  举报