莫比乌斯函数(P3455 题解)
题目链接。
我们定义 的莫比乌斯函数为 。
我们将 分解质因式后为 则
,就等价于 。
即为找到 满足 和 。
假如不考虑条件 ,我们令 。则答案为 。
想必大家都知道容斥原理把,即答案为
其中 表示 即 中所有 的倍数的个数。
然后根据上面 的定义可得答案为 。
然后我们可以从 入手,我们发现必定可以分成若干个极大段,使得段内值相等。
我们考虑对于一个分数 ,找到一个最大的整数 ,满足 。
则 。
如果满足以上条件即满足 和 。
证明条件 。
证明条件 。
设 ,其中 。
在设 ,其中 。
从上面 可知,。
结论:将这些数分段段数必定是 的。
然后我们就可以每次跳到 的末尾,再求出 的前缀和,然后根据分配律来求出上面的值。
#
#include <bits/stdc++.h>
#define x first
#define y second
#define IOS ios::sync_with_stdio(false)
#define cit cin.tie(0)
#define cot cout.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 50010, M = 100010, MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const LL LLINF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;
int primes[N], cnt;
bool st[N];
int mob[N], sum[N];
void solve();
void get_primes(int n)
{
mob[1] = 1;
for (int i = 2; i <= n; i ++ )
{
if (!st[i])
{
primes[cnt ++ ] = i;
mob[i] = -1;
}
for (int j = 0; primes[j] <= n / i; j ++ )
{
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0) break;
mob[t] = mob[i] * -1;
}
}
for (int i = 1; i <= n; i ++ ) sum[i] = sum[i - 1] + mob[i];
}
int main()
{
IOS;
cit, cot;
get_primes(N - 1);
int T = 1;
cin >> T;
while (T -- ) solve();
return 0;
}
void solve()
{
int a, b, d;
cin >> a >> b >> d;
a /= d, b /= d;
LL res = 0;
for (int l = 1, r; l <= min(a, b); l = r + 1)
{
r = min(a / (a / l), b / (b / l));
res += (sum[r] - (LL)sum[l - 1]) * (a / l) * (b / l);
}
cout << res << endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效