/*数论:给你 a , b , c , d , k 五个值 (题目说明了 你可以认为 a=c=1) x 属于 [1,b] ,y属于[1,d]
让你求有多少对这样的 (x,y)满足gcd(x,y)==k。给你的时间是 3000 MS。 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000
原文链接:https://blog.csdn.net/lixuepeng_001/article/details/50577932 */
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1e5+7;
int mu[maxn],couot=0,visit[maxn],prime[maxn];
void mobius()
{
memset(visit,0,sizeof(visit));
memset(prime,0,sizeof(prime));
memset(mu,0,sizeof(mu));
mu[1]=1;
for(int i=2;i<maxn;i++)
{
if(visit[i]==0)
{
prime[couot++]=i;
mu[i]=-1;
}
for(int j=0;j<couot&&i*prime[j]<maxn;j++)
{
visit[i*prime[j]]=1;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
else
{
mu[i*prime[j]]=-mu[i];
}
}
}
}
int main()
{
int m,n,k,l,t,a,b,sum=0;
scanf("%d",&t);
mobius();
while(t--)
{
scanf("%d %d %d %d %d",&a,&m,&b,&n,&k);//m,n为x,y的取值范围,k为两个的最大公约数;
cout<<"Case "<<++sum<<": ";
if(k==0){
cout<<"0"<<endl;
continue;
}
int lm,ln,temp,d;
lm=m/k;//通过改变区间,转换为求两个数互质的对数有多少个,让d=1;
ln=n/k;
temp=min(lm,ln);
long long ans1=0,ans2=0;
for(int i=1;i<=temp;i++)
{
ans1+=(long long)mu[i]*(lm/i)*(ln/i);
}
for(int i=1;i<=temp;i++)//形如(1,2),(2,1)就是重复的,应该删去,用这条语句删
{
ans2+=(long long)mu[i]*(temp/i)*(temp/i);
}
printf("%lld\n",(long long)(ans1-ans2/2));
}
}
acm算法之莫比乌斯反演
最新推荐文章于 2024-05-22 08:59:36 发布