题目
给定a,b,c,d,k,
其中a=c=1,a<=b<=1e5,c<=d<=1e5,0<=k<=1e5
求
思路来源
https://www.cnblogs.com/iiyiyi/p/5635303.html
题解
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
bool ok[maxn];
int prime[maxn],mu[maxn],cnt;
int T;
ll a,b,c,d,k,up;
ll ans1,ans2;
void sieve()
{
mu[1]=1;
for(ll i=2;i<maxn;++i)
{
if(!ok[i])
{
prime[cnt++]=i;
mu[i]=-1;
}
for(int j=0;j<cnt;++j)
{
if(i*prime[j]>=maxn)break;
ok[i*prime[j]]=1;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;//如果开的是全局,就不用管
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
}
int main()
{
sieve();
scanf("%d",&T);
for(int cas=1;cas<=T;++cas)
{
ans1=ans2=0;
scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);
printf("Case %d: ",cas);
if(!k)
{
puts("0");
continue;
}
b/=k;d/=k;
up=min(b,d);
for(int i=1;i<=up;++i)
ans1+=mu[i]*(b/i)*(d/i);
for(int i=1;i<=up;++i)
ans2+=mu[i]*(up/i)*(up/i);//[1,min(b,d)][min(b,d),max(b,d)],前者被算了两次,后者一次
printf("%lld\n",ans1-ans2/2);
}
return 0;
}