Description
FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a
,y<=b,并且gcd(x,y)=d。作为FGD的同学,FGD希望得到你的帮助。
Input
第一行包含一个正整数n,表示一共有n组询问。(1<=n<= 50000)接下来n行,每行表示一个询问,每行三个
正整数,分别为a,b,d。(1<=d<=a,b<=50000)
Output
对于每组询问,输出到输出文件zap.out一个正整数,表示满足条件的整数对数。
Sample Input
2
4 5 2
6 4 3
Sample Output
3
2
莫比乌斯模板题
#include<bits/stdc++.h>
using namespace std;
const int maxn = 50100;
int prime[maxn] , miu[maxn];
bool flag[maxn];
int read()
{
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
void first(){
miu[1] = 1;
for(int i = 2;i <= maxn;++i)
{
if(!flag[i])
prime[++prime[0]] = i , miu[i] = -1;
for(int j = 1;j <= prime[0] && i * prime[j] <= maxn;++j)
{
flag[i * prime[j]] = true;
if(i % prime[j] == 0) break;
miu[i * prime[j]] = -miu[i];
}
}
for(int i = 1;i <= maxn;++i)
miu[i] += miu[i - 1];
return;
}
long long solve(int x,int y,int p){
long long ans = 0;
if( x > y ) swap(x,y);
x /= p;y /= p;
int d = 1;
int Max = min( x , y );
while( d <= Max )
{
int i = min( x / ( x / d ) , y / ( y / d ));
ans = ans + 1ll * (miu[i] - miu[d - 1]) * (x/d) * (y/d);\
d = i + 1;
}
return ans;
}
void init(){
int T = read();
while(T--)
{
int a = read() , b = read() , d = read();
printf("%lld\n",solve(a,b,d));
}
return;
}
int main(){
first();
init();
return 0;
}