题意:
和Gcd HYSBZ - 2818几乎一样,在区间[ a , b ] 取一个x,在区间[ c , d ] 取一个y,求 得gcd(x,y)=k的对数
同时 (x,y) 与(y,x)为一对,斌且这里a=c=1。
思路:
这里我们可以延续上次的套路,分段去取莫比乌斯前缀和,但是这里怎么去除 (y,x)?
我是这样想的 当只有x与y的区间相同,除去gcd(1,1),其他的都有重复,也就是说
Solve(n,m)表示在区间[ a , b ] 取一个x,在区间[ c , d ] 取一个y,求 得gcd(x,y)=1的对数
solve(n,m)- solve(n,n)/2就是答案
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100000
bool check[MAXN+10];
int prime[MAXN+10];
int mu[MAXN+10];
int sum[MAXN+10];
void Moblus()
{
memset(check,false,sizeof(check));
mu[1]=1;
int tot = 0;
for(int i = 2; i <= MAXN; i++)
{
if( !check[i] )
{
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot; j++)
{
if(i * prime[j] > MAXN) break;
check[i * prime[j]] = true;
if( i % prime[j] == 0)
{
mu[i * prime[j]] = 0;
break;
}
else
{
mu[i * prime[j]] = -mu[i];
}
}
}
sum[0]=0;
for (int i = 1; i <= MAXN; i++)
{
sum[i] = sum[i - 1] + mu[i];
}
}
// ÕÒ[1, n], [1, m]ÄÚgcd(i,j)=1µÄÊý¶ÔµÄ¸öÊý
long long s(int n,int m)
{
long long ans = 0;
if (n > m) swap(n, m);
for (int i = 1, la = 0; i <= n; i = la + 1)
{
la = min(n / (n / i), m / (m / i));
ans += (long long)(sum[la] - sum[i - 1]) * (n / i) * (m / i);
}
return ans;
}
int main()
{
Moblus() ;
int n,kk=1;
int a,b,c,d,k;
long long ans;
scanf("%d",&n);
while(n--)
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
if(k==0) ans =0;
else
{
if (b > d) swap(b, d);
ans=s(b/k,d/k) - s(b/k,b/k)/2;
}
printf("Case %d: %lld\n",kk++,ans);
}
}