题解 P4450 【双亲数】
upd:256 天后的更新,修复了错误和公式格式,充实了内容
如果
under 题解 P4450
蒟蒻第一道莫反题
本题解适合新手学习基础,dalao 请跳过,不要嘲讽 qwq
前置知识:
单位函数(\epsilon ):
即当且仅当 i = 1 时取值取值为 1,否则为 0。很简单对不对?
Dirichlet 卷积(\ast ):
Dirichlet 卷积是数论函数之间的运算。即
其中
也可以写作
我们发现:
Mobius 函数(\mu ):
其中
Mobius 变换
设
则称
推一下式子。
即
至此就可以来做这道题了。
回到了原题。题目要求的是
对式子进行套路性的变形
出现了
(似乎越来越丑了)此时可以把
至此,计算答案可以
算法还可以继续优化。发现式子里还有两个形如
code 1
std::bitset<1000003> v;
int p[78501], mu[1000003];
void sieve(int N) {
int m = 0;
v.set(1), mu[1] = 1;
for (int i = 2; i <= N; ++i) {
if (!v[i]) p[++m] = i, mu[i] = -1;
for (int j = 1; j <= m && i * p[j] <= N; ++j) {
v.set(i * p[j]);
if (i % p[j] == 0) break;
mu[i * p[j]] = -mu[i];
}
mu[i] += mu[i - 1];
}
}
int main() {
int A, B, d;
long long ans = 0;
std::cin >> A >> B >> d;
A /= d, B /= d;
if (A > B) std::swap(A, B);
sieve(A);
for (int l = 1, r, a, b; l <= A; l = r + 1) {
a = A / l, b = B / l;
r = std::min(A / a, B / b);
ans += 1ll * a * b * (mu[r] - mu[l - 1]);
}
std::cout << ans << '\n';
return 0;
}
code 2
如果你像我一样闲得难受,可以学来杜教筛写写这题,复杂度好像还更高了。
不会杜教筛但想学的朋友可以来看我的这篇题解。
这个多次询问的题目让我对杜教筛及空间优化有了更深入的理解(
std::bitset<10003> v, vm;
int MX, base, p[1231], mu[10003], mu_[10003];
inline int to(int x) {
return MX / x;
}
void sieve(int N); // 同 code 1
int getMu(int N) {
if (N <= base) return mu[N];
if (vm[to(N)]) return mu_[to(N)];
int ans = 0;
for (int l = 2, r, L; l <= N; l = r + 1) {
L = N / l, r = N / L;
ans += (r - l + 1) * getMu(L);
}
vm.set(to(N));
return mu_[to(N)] = 1 - ans;
}
int main() {
int A, B, d;
long long ans = 0;
std::cin >> A >> B >> d;
A /= d, B /= d;
if (A > B) std::swap(A, B);
MX = A, base = pow(A, 2. / 3);
sieve(base);
for (int l = 1, r, a, b, gR, gL; l <= A; l = r + 1) {
a = A / l, b = B / l;
r = std::min(A / a, B / b);
vm.reset(), gR = getMu(r);
vm.reset(), gL = getMu(l - 1);
ans += 1ll * a * b * (gR - gL);
}
std::cout << ans << '\n';
return 0;
}