思路:最基本的gcd的莫比乌斯反演推式子,突然感觉gcd的好像都差不多。
还是很难将反演的两个式子灵活运用。
推式子先留个坑,以后补。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<map>
#include<queue>
using namespace std;
const int inf = 0x3f3f3f3f;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 100000 + 50;
ll mu[MAXN];
bool check[MAXN + 10];
int prime[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];
}
}
}
}
int main(void) {
int t;
scanf("%d", &t);
int ff = 1;
Moblus();
while (t--) {
int a, b, c, d, k;
scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
printf("Case %d: ", ff++);
if (k == 0) {
printf("0\n");
continue;
}
b = b / k;
d = d / k;
int up = min(b, d);
ll ans=0;
for (int i = 1; i <= up; i++) {
ans += (long long)mu[i] * (b / i)*(d / i);
}
ll ans2 = 0;
for (int i = 1; i <= up; i++) {
ans2 += (long long)mu[i] * (up / i)*(up / i);
}
printf("%lld\n", ans-ans2/2);
}
return 0;
}