转载自 walker
前置知识
- 假设
能唯一分解为 ,莫比乌斯函数 定义为:
题目分析
给定
证明:假设
,那么 ,矛盾。
可以用容斥原理求解,设
有一个质公因子的方案数量:
有两个质公因子的方案数量:
有三个质公因子的方案数量:
所以根据容斥原理,合法方案数为:
注意到符号项就是莫比乌斯函数,故合法方案数可用莫比乌斯函数表示:
注意,
中因子 的个数就是 个,不仅只有质因子有这样的性质
如果直接枚举
我们发现,这个式子理论上
分块证明:
分段讨论:
- 当
时,因为 是 中的整数,所以只有 个不同的 值。 - 当
时, ,又因为式子取整了,所以式子只能取到 的值,故最多也只有 个不同的 值。
有关当
由于下取整,所以
图和证明引自:墨染空
我们现在已经证明出了,可以将一段 长度为
假设有
我们要证明的是
由于:
故
所以
用带余除法证明第二部分:
设
所以等价于证明
等价于证明
再令
由于
代码实现
// Author: CodeBoy
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define Re register
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) > (b) ? (b) : (a))
using namespace std;
typedef long long ll;
const int N = 50010;
int primes[N], cnt;
bool st[N];
int mobius[N], sum[N];
void init(int n)
{
mobius[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!st[i])
{
primes[cnt++] = i;
mobius[i] = -1;
}
for (int j = 0; primes[j] * i <= n; j++)
{
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0)
{
mobius[t] = 0;
break;
}
mobius[t] = mobius[i] * -1;
}
}
for (int i = 1; i <= n; i++)
sum[i] = sum[i - 1] + mobius[i];
}
int main()
{
init(N - 1);
int t;
scanf("%d", &t);
while (t--)
{
int a, b, d;
scanf("%d%d%d", &a, &b, &d);
a /= d, b /= d;
int n = min(a, b);
ll res = 0;
for (int l = 1, r; l <= n; l = r + 1)
{
r = min(n, min(a / (a / l), b / (b / l)));
res += (sum[r] - sum[l - 1]) * (ll)(a / l) * (b / l);
}
printf("%lld\n", res);
}
return 0;
}