数论大学习2
继 Pollard-Rho 后又一次讲到了杜教筛,遂再来写一篇题解趁热打铁一下
狄利克雷卷积
对于两个数论函数
狄利克雷这么定义是有他的道理,我们发现这个运算满足交换律、结合律、分配律,而且两个积性函数的狄利克雷卷积还是积性函数,均可推式子求证
还是定义:
-
1$: $f(x)=1 -
\varepsilon$: 单位元,对于任意数论函数 $f$,有 $f * \varepsilon=f$,具体内容是 $\varepsilon(x)=[x=1] -
id^k$: 幂函数,$id^k(x)=x^k$,$k=1$ 时可省略 $k -
-
\varphi$: 欧拉函数,$\varphi(x)=\sum_{i=1}^x[\gcd(i,x)=1]=x\prod_{p\in P,p|x}\frac{p-1}{p}
那么我们就可以发现:
-
\varepsilon=\mu * 1 -
\varphi=\mu * id -
id=\varphi * 1
还有很多别的常用卷积式,不过已经够了
杜教筛
定义大写字母为原函数的前缀和,例
我们需要快速求解
对于任意一个数论函数
进而便有:
于是如果
然而复杂度正确吗?首先可以预处理
然后再进行递归,设求
于是使用均值不等式,当
模板代码:
int F(int n) {
if (n <= m) return init[n]; // 预处理
if (mp[n]) return mp[n]; // 记忆化
int ans = H(n);
for (int l = 2, r; l <= n; l = r + 1) {
r = n / (n / l); // 根号分治
ans -= (G(r) - G(l - 1)) * F(n / l);
}
return mp[n] = ans / g1;
}
【模板】杜教筛
求
\sum_{i=1}^n\mu(n),\sum_{i=1}^n\varphi(n)
根据
code:
#include <bits/stdc++.h>
#define eps 1e-12
#define inf LONG_LONG_MAX
#define int long long
#define endl '\n'
using namespace std;
const int maxn = 1e6 + 10, mod = 998244353;
vector<int> pr;
map<int, int> mphi, mmu;
int m, iphi[maxn], imu[maxn], ntp[maxn];
int mu(int n) { // mu * 1 = epsilon
if (n <= m) return imu[n];
if (mmu[n]) return mmu[n];
int ans = 1;
for (int l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
ans -= (r - l + 1) * mu(n / l);
}
return mmu[n] = ans;
}
int phi(int n) { // phi * 1 = id
if (n <= m) return iphi[n];
if (mphi[n]) return mphi[n];
int ans = n * (n + 1) / 2;
for (int l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
ans -= (r - l + 1) * phi(n / l);
}
return mphi[n] = ans;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
m = 1000000;
ntp[1] = iphi[1] = imu[1] = 1;
for (int i = 2; i <= m; i++) {
if (!ntp[i]) pr.push_back(i), iphi[i] = i - 1, imu[i] = -1;
for (int p : pr) {
if (i * p > m) break;
ntp[i * p] = 1;
if (i % p == 0) {
iphi[i * p] = iphi[i] * p;
break;
}
iphi[i * p] = iphi[i] * (p - 1);
imu[i * p] = -imu[i];
}
}
for (int i = 1; i <= m; i++) imu[i] += imu[i - 1], iphi[i] += iphi[i - 1];
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
cout << phi(n) << " " << mu(n) << endl;
}
return 0;
}
似乎能水一篇题解...