积性函数

积性函数

定义

  1. f(n) 的定义域为正整数域,值域为复数,即 f:Z+C,则称 f(n)数论函数
  2. f(n) 为数论函数,且 f(1)=1,对于互质的正整数 p,qf(pq)=f(p)f(q),则称其为 积性函数
  3. f(n) 为积性函数,且对于任意正整数 p,q 都有 f(pq)=f(p)f(q),则称其为 完全积性函数

性质

  1. 对于任意积性函数 f(1)=1
  2. 对于任意积性函数 f,gfg 依然是积性函数

积性函数的例子

  1. 除数函数 σk(n)=d|ndk
  2. 约数个数函数 σ0(n)=τ(n)=d|n1
  3. 约数和函数 σ(n)=d|nd
  4. 欧拉函数 φ(n)
  5. 莫比乌斯函数 μ(n)
  6. 元函数 ϵ(n)=[n=1] 完全积性
  7. 恒等函数 I(n)=1​ 完全积性
  8. 单位函数 id(n)=n 完全积性
  9. 幂函数 idk(n)=nk 完全积性

欧拉函数

定义

对于正整数 nφ(n) 的等于 1n1 中与 n 互质的数的个数,规定 φ(1)=1

通项公式:φ(n)=ni=1k(11pi),其中 n 的质因数分解形式为 n=i=1kpiai

性质

以下不特加说明,默认 p 为素数

  1. φ(p)=p1

  2. φ(pk)=pkpk1=(p1)pk1

    证明:

    小于 pk 的数一共有 pk1 个,其中不与 pk 互素的数的个数为 1p,2p,,(pk11)p,一共 pk11

  3. n 的质因数分解形式为 n=i=1kpiai,则 φ(n)=ni=1k(11pi)

    证明:

    φ(n)=i=1kφ(piai)=ni=1k(11pi)

  4. 欧拉定理:如果 a,m 互质,则一定有 aφ(m)1(modm)

  5. 费马小定理:ap11(modp)

  6. i=1ni[(n,i)=1]=n×[n=1]+φ(n)2

    证明:

    如果 (n,i)=1,则 (n,ni)=1

    由此可知,与 n 互质的数成对存在,并且先加等于 n

  7. p|n,则 φ(np)=pφ(n),否则 φ(np)=(p1)φ(n)

    参考通项公式

  8. φ(ab)=φ(a)φ(b)(a,b)φ((a,b))

    (a,b)=1,则结论显然,所以下面只考虑 ab 不互质的情况

    我们考虑将 φ(n) 写成 φ(n)=ni=1m(11pi)

    那么 φ(a)φ(b) 相当于 φ(ab)p|(a,b)(11p)

    (a,b)φ((a,b)) 正好等于后面那个多余的东西的倒数

  9. 狄利克雷卷积的结果

    d|nφ(d)=n

线性筛求欧拉函数

1
2
3
4
5
6
7
8
9
10
11
void init_phi(int n) {
phi[1] = 1;
for (int i = 2; i <= n; ++i) {
if (!isp[i]) pri[++cnt] = i, phi[i] = i - 1;
for (int j = 1; j <= cnt && i * pri[j] <= n; ++j) {
isp[i * pri[j]] = 1;
if (i % pri[j] == 0) { phi[i * pri[j]] = phi[i] * pri[j]; break; }
phi[i * pri[j]] = phi[i] * (pri[j] - 1);
}
}
}

莫比乌斯函数

定义

μ(n)={1,n=1(1)k,n=i=1kpi0

性质

  1. i=1nμ2(i)=i=1nμ(i)ni2

    证明:

    注意到上式左边是求无平方因子的数的个数,我们令 f(n) 表示最大的整除 n 的平方因子

    那么左式等价于 i=1n[f(i)=1]=d|f(i)μ(d)

    我们注意到当 d 含有平方因子的时候 μ(d)=0,当且仅当 d 不含平方因子的时候 μ(d)0

    那么这时候一定有 d2|f(i),我们知道 if(i) 一定不含平方因子,所以可以直接 d2|f(i)d2|i

    那么我们有 i=1n[f(i)=1]=i=1nd|f(i)μ(d)=i=1nd2|iμ(d)=i=1nμ(i)d2|i1=i=1nμ(i)ni2

  2. 狄利克雷卷积的结果

    d|nμ(d)=[n=1]

    d|nμ(d)nd=φ(n)

狄利克雷卷积

定义

f,g 是两个数论函数,则 fg=d|nf(d)g(nd)

性质

  1. 交换律
  2. 结合律
  3. 加法的分配率 $$
  4. 两个积性函数的狄利克雷卷积仍然是积性函数
  5. 积性函数的逆元仍然是积性函数
  6. 积性函数相乘仍然是积性函数
  7. 如果 f 为完全积性函数,(fg)(fh)=f(gh)

逆元

对于数论函数 f,若存在 g,使得 fg=ϵ,则称 gf 的逆元

对于数论函数 f,当 f(1) 不为 1 时,存在逆元 g(n)=1f(1)([n=1]d|n,d1f(d)g(nd))

常用的狄利克雷卷积

  1. μI=ϵ
  2. φI=id
  3. μid=φ
  4. II=τ,idI=σ,σk=idkI

狄利克雷前缀和

大概就是令 sn=d|nad,我们称 sa 的狄利克雷前缀和,从狄利克雷卷积的角度来考虑,这个东西就是 1a,从高维前缀和的角度考虑,这东西就是以每个质因子为一个维度的前缀和,然后这东西可以做到 O(nloglogn)

1
2
for (int i = 1; i <= cnt; ++i)
for (int j = 1; pri[i] <= n / j; ++j) s[pri[i] * j] += s[j];

线性筛

如果一个积性函数在素数的答案可以简单求得,且其最小质因数的次数不为一的时候的答案也可以简单计算,那么我们可以直接用线性筛 O(n) 来求这个积性函数,以 φ(n) 为例

1
2
3
4
5
6
7
8
9
10
11
void init_phi(int n) {
phi[1] = 1;
for (int i = 2; i <= n; ++i) {
if (!isp[i]) pri[++cnt] = i, phi[i] = i - 1;
for (int j = 1; j <= cnt && i * pri[j] <= n; ++j) {
isp[i * pri[j]] = 1;
if (i % pri[j] == 0) { phi[i * pri[j]] = phi[i] * pri[j]; break; }
phi[i * pri[j]] = phi[i] * (pri[j] - 1);
}
}
}

否则就要麻烦一点,先求出这个积性函数在 pc 的答案,然后再利用积性函数的性质求出所有位置的答案

f(n)=d|ndφ(d) 为例,其中 an 表示 n 去掉其最小质因子所有次方后的值

注意到这样做的时间复杂度仍然是 O(n)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void init_isp(int n) {
for (int i = 2; i <= n; ++i) {
if (!isp[i]) pri[++cnt] = i;
for (int j = 1; j <= cnt && i * pri[j] <= n; ++j) {
isp[i * pri[j]] = 1;
if (i % pri[j] == 0) { a[i * pri[j]] = a[i]; break; }
a[i * pri[j]] = i;
}
} h[1] = 1;
for (int i = 1; i <= cnt; ++i)
for (ll j = pri[i]; j <= n; j *= pri[i])
h[j] = h[j / pri[i]] + (j - j / pri[i]) * j;
for (int i = 2; i <= n; ++i)
if (a[i] > 1) h[i] = h[i / a[i]] * h[a[i]];
}

杜教筛

众所周知,积性函数前缀和可以 O(n) 预处理,但如果数据范围高达 109 的话就无计可施了,这个时候就只能用杜教筛了

不妨设所求为 S(n)=i=1nf(i), 我们根据玄学选取另一积性函数 g(i)

t=1n(fg)(t)=t=1nd|tg(d)f(td)=d=1nd|tg(d)f(td)=d=1ng(d)d|tf(td)=d=1ng(d)k=1ndf(k)=d=1g(d)S(nd)

t=1n(fg)(t)=t=1ng(t)S(nt)g(1)S(n)=t=1n(fg)(t)t=2ng(t)S(nt)

如果我们能快速的计算 g​ 的前缀和以及 fg​ 的值,那么我们可以用数论分块做到 O(n23)​ 的复杂度

关于杜教筛的一些时间复杂度:

  1. 预处理前 n23 项,时间复杂度 O(n23)
  2. 不预处理前 n23 项,时间复杂度 O(n34)
  3. 数论分块套数论分块,不预处理时间复杂度 O(n34),预处理时间复杂度 O(n23)
  4. 数论分块套杜教筛,时间复杂度 O(n23)

i=1nφ(i) 为例,对于两个函数我们选择的 g 均为恒等函数 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace D_Seive {
const int N = 1000000; // n ^ 2/3
ll _g[maxn], n; bool vis[maxn]; int sn; // n ^ 1/2

void init(ll _n) {
n = _n; sn = sqrt(n);
for (int i = 1; i <= 2 * sn; ++i) vis[i] = 0;
}
int get(ll x) { return x <= sn ? x : sn * 2 - n / x + 1; }
ll calc(ll n) {
if (n <= N) return g[n];
int id = get(n);
if (vis[id]) return _g[id]; ll ans = F1(n); // n * (n + 1) / 2
for (ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
ans = (ans - (r - l + 1) * calc(n / l)) % p;
}
return vis[id] = 1, _g[id] = ans;
}
}

有的时候,unordered_map 比用 Div_Hash 还要快

Min_25筛

简介

Min_25 筛是一种能够快速求解积性函数 f(x) 的前缀和 i=1nf(i) 的筛法,前提是 f(p) 是关于 p 的多项式,同时 f(pk) 可以快速计算

时间复杂度为 O(n34logn),空间复杂度 O(n)

推导过程

下文中,我们令 f(i) 为在素数处和原函数相同的完全积性函数,这样做的原因是 g 数组我们只需要用到 g(n,|P|)

i=1nf(i)=f(1)+pPpnf(p)+pPpxnpnf(px)(inpxLPF(i)>pf(i)+[x>1])​​​

大概就是将 f(x) 的前缀和分成三部分,f(1)​、质数以及合数的情况,至于合数的情况,我们是通过枚举最小质因子来枚举合数的

至于如何计算这几个部分,我们考虑构造函数 g(n,m)g(n,m)=i=1n[iPLPF(i)>Pm]f(i)

这个东西就是我们只算所有的素数以及最小质因子大于第 m 个素数的数

容易得到 g(n,m) 的递推式

g(n,m)={g(n,m1),Pm2>ng(n,m1)f(Pm)(g(nPm,m1)g(Pm1,m1)),Pm2n

简单来讲就是 g(n,m) 一定是 g(n,m1) 减掉最小质因数为 Pm 的合数的贡献,因为 f(i) 是完全积性函数,所以我们考虑将 Pm 提出来,需要注意的是我们需要将素数的贡献减掉

然后我们再构造一个函数,S(n,m)=i=1n[LPF(i)>Pm]ik​​,那么我们可以将 S​​ 和 g​​ 以某种关系连接起来,另外为了方便,我们把 g(n,|P|)=pPnpk​ 简写成 g(n)​​

容易得到 S(n,m)=g(n)i=1m1Pik+Pixni>m(Pix)k(S(nPix,i)+[x>1])​​​​​​

大概就是分成两部分,第一部分是大于 Pm 的质数,另一部分是最小质因子大于 Pm 的合数

最后的答案显然就是 S(n,0)

模板

求积性函数 f(x)​ 的前缀和,其中 f(px)=px

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ll id1[maxn], id2[maxn]; int Sn;
int get_id(ll x) { return x <= Sn ? id1[x] : id2[n / x]; }

ll g[maxn], w[maxn], inv2; int num;
void init_min25(ll n) {
inv2 = pow_mod(2, p - 2);
for (ll l = 1, r; l <= n; l = r + 1) {
r = n / (n / l); w[++num] = n / l; ll t = n / l % p;
g[num] = t * (t + 1) % p * inv2 % p - 1; // 注意需要把 f(1) 减掉
if (w[num] <= Sn) id1[w[num]] = num;
else id2[n / w[num]] = num;
}
for (int i = 1; i <= cnt; ++i)
for (int j = 1; j <= num && 1ll * pri[i] * pri[i] <= w[j]; ++j) {
g[j] = (g[j] - pri[i] * (g[get_id(w[j] / pri[i])] - sp[i - 1])) % p;
}
}

ll S(ll n, int m) {
if (pri[m] >= n) return 0;
ll ans = (g[get_id(n)] - sp[m]) % p;
for (int i = m + 1; i <= cnt && 1ll * pri[i] * pri[i] <= n; ++i)
for (ll x = 1, mul = pri[i]; mul <= n; mul *= pri[i], ++x)
ans = (ans + mul * (S(n / mul, i) + (x > 1))) % p;
return ans;
}

powerful number筛

简介

powerful number:每个质因子次数都不为 1 的数,n 的 powerful number 只有 O(n)

f(x) 为要求的积性函数,我们需要构造一个积性函数 g(x) 需要满足 g(p)=f(p),同时我们需要求一个积性函数 h(x),满足 f=gh,在素数处我们有 f(p)=g(1)h(p)+g(p)h(1),因为我们有 g(1)=h(1)=1,g(p)=f(p),所以我们可以得到 h(p)=0,由于 h 是积性函数,那么当且仅当 xpowerful number 时,h(x) 才不为 0,那么 f 的前缀和可以写成 i=1nf(i)=i=1nh(i)j=1nig(j),这个东西需要我们能够快速求 g(x) 的前缀和,一般情况下我们需要使用 min25 或者杜教筛来求 g(x) 的前缀和,关于 h(x) 我们直接枚举所有 powerful number 即可,所以关于 h(x) 我们只需要知道 h(px) 的值,一般有两种方法,第一种是手动求一下,第二种就是递推一下,因为我们显然有 h(pk)=f(pk)i=0k1h(pi)g(pki)

模板

1
2
3
4
5
6
7
ll dfs(int k, ll m, ll h) { // 枚举所有 powerful number
ll ans = h * D_Seive::sg(n / m) % p;
for (ll res = n / m; 1ll * pri[k] * pri[k] <= res; ++k)
for (ll e = 2, t = 1ll * pri[k] * pri[k]; t <= res; t *= pri[k], ++e)
ans = (ans + dfs(k + 1, m * t, h * ch(pri[k], e, t) % p)) % p;
return ans;
}

递推 h(x) 并不影响复杂度

1
2
3
4
5
6
7
8
9
10
11
12
ll dfs(int k, ll m, ll h) {
ll ans = h * D_Seive::sg(n / m) % p;
for (ll res = n / m; 1ll * pri[k] * pri[k] <= res; ++k) {
vector<ll> _h { 1, 0 }, g { 1, cg(pri[k], pri[k]) };
for (ll e = 2, t = 1ll * pri[k] * pri[k]; t <= res; t *= pri[k], ++e) {
_h.push_back(cf(t)); g.push_back(cg(pri[k], t));
for (ll o = 0; o < e; ++o) _h[e] = (_h[e] - _h[o] * g[e - o]) % p;
ans = (ans + dfs(k + 1, m * t, h * _h[e] % p)) % p;
}
}
return ans;
}

例题

  1. 简要题意:求 i=1nj=1m[(i,j)=k]

    n,m,k5×104

    简要题解:i=1nj=1m[(i,j)=k]=d=1nkμ(d)ndkmdk

    O(n) 预处理后可以做到单次 O(n)

    Luogu P3455 [POI2007]ZAP-Queries

  2. 简要题意:pi=1nj=1m[(i,j)=p]

    T=104,n,m107

    简要题解:pi=1nj=1m[(i,j)=p]=T=1nnTmTp|Tμ(Tp)

    O(n) 预处理后可以做到单次 O(n)

    Luogu P2257 YY的GCD

  3. 简要题意:i=1nj=1m(i,j)k

    n,m5×106,T2×103

    简要题解:i=1nj=1m(i,j)k=T=1nnTmTt|Ttkμ(Tt)

    O(n) 预处理后可以做到单次 O(n)

    Luogu P4449 于神之怒加强版

  4. 简要题意:i=1nj=1m[i,j]

    n,m107

    简要题解:i=1nj=1m[i,j]=T=1nnT(nT+1)2mT(mT+1)2Td|Tdμ(d)

    O(n) 预处理后可以做到单次 O(n)

    Luogu P1829 [国家集训队]Crash的数字表格 / JZPTAB

  5. 简要题意:i=1nj=1n[ai,aj]

    n2×105,ai106

    简要题意:i=1nj=1n[ai,aj]=T=1N1T(T|aiai)2d|Tdμ(d)

    可以做到 O(nlogn)

    AtCoder AGC038C LCMs

  6. 简要题意:给定 n​,求所有长度为 n​ 的 01​ 串的价值总和,一个 01​ 串的价值定义为 nk​,其中 k​ 是这个 01​​ 串的最小周期

    n109

    简要题解:

    i=1n2nif(i)+2ni=1n2f(i)=2n+i=1n2(ni1)f(i)

    2x=d|xf(d),也就是说 (f1)(n)=2n,可以直接上杜教筛

    2021杭电多校4 C Cycle Binary

  7. 简要题意:定义积性函数 f(x),且 f(px)=(px)2px,求 i=1nf(i)

    n1010

    简要题解:直接上 Min_25​​ 筛

    Luogu P5325 【模板】Min_25筛

  8. 简要题意:求 1n 的素数个数

    n1011

    简要题解:我们令 f(x)=1,这东西显然是完全积性函数,然后直接 Min_25 筛即可

    Loj 6235 区间素数个数

  9. 简要题意:给定 n​,求 12i=1nσ02(i)σ0(i)

    n1010

    简要题解:注意到 i=1nσ0(i)=i=1nni​,对于 i=1nσ02(i) 我们可以考虑用 Min_25

    我们令 f(x)=σ0(x)2,这个东西显然是积性函数,且 f(px)=(x+1)2

    Loj 6682 梦中的数论

  10. 简要题意:求 i=1nj=1mτ(i)τ(j)τ((i,j))

    n,m2×106

    简要题解:i=1nj=1mτ(i)τ(j)τ((i,j))=T=1ni=1nTτ(iT)j=1mTτ(jT)t|Tτ(t)μ(Tt)

    我们考虑后面那个东西 d|nτ(d)μ(nd),这个东西就是 IIμ 显然等于 I

    那么我们只需要求 T=1ni=1nTτ(iT)j=1mTτ(jT)

    注意到这个东西就是 T=1n(d|inτ(d))(d|imτ(d)),这是个狄利克雷后缀和的形式,可以做到 O(nloglogn)

    Luogu P6810 「MCOI-02」Convex Hull 凸包

  11. 简要题意:求 i=1nj=1n(i+j)kf((i,j))(i,j)​,其中 f(n) 当且仅当 n 无平方因子时为 1

    n5×106,k1018

    简要题解:i=1nj=1n(i+j)kf((i,j))(i,j)=T=1nTki=1nTj=1nT(i+j)kt|Ttf(t)μ(Tt)

    我们令 S(n)=i=1nj=1n(i+j)kF(n)=i=1nikG(n)=i=1nF(i),容易得到 S(n)=G(2n)2G(n)

    后面那个东西显然是 d|ndμ(d)μ(nd),对于 n=pk,当 k>2 时为 0,这个东西可以线筛

    另外自然数幂和也可以线筛,因为他是完全积性函数,可以做到 O(n) 预处理,单词询问 O(n)

    Luogu P6156 简单题

  12. 简要题意:求 i1=1ni2=1nik=1n[i1,i2,,ik]mod998244353​​

    n106,k10100,T=1000

    简要题意:我们考虑单独算每个质数 p 的贡献

    我们注意到 lcm=pt​​ 太难计算,考虑换成 pt|lcm​​ 的方式来计算

    对于一个 lcm=pt​ 的 k​ 元组,我们考虑分别算 t​ 次贡献,每次贡献为 p​​,那么我们可以这样计算贡献,令 fi(p)​ 表示 pi|[i1,i2,,ik]​ 的 k​ 元组个数,这样一个 p​ 的贡献就是 pi=1logpnfi(p)

    容易得到 fi(p)=nk(nnpi)k​, 这个整除启示我们进行数论分块

    我们可以预处理出前缀 ipt 的乘积,然后就可以直接数论分块,另外对于 k 我们直接对 φ(φ(998244353)) 取模即可,预处理 O(n)​,单次询问 O(nlogn)

    Luogu P7360 「JZOI-1」红包

  13. 简要题意:给定一个长度为 n 的排列 p,求 i=1nj=1n(i,j)(ai,aj)

    n105

    简要题解:首先我们划一下式子,这里扔掉 (i,j),我们采用 φ 而不是 μ,能够得到 d=1nφ(d)d|id|j(ai,aj)

    我们考虑对于一个 d,不妨设有 mai,那么贡献就是 i=1mj=1m(ai,aj),用类似的式子化简可得 d=1nφ(d)(i=1m[d|ai])2

    我们考虑一个暴力,暴力枚举 d,然后暴力枚举这 mai,然后对于这些 ai,暴力枚举约数

    容易得到时间复杂度为 O(i=1nτ(i)τ(ai))​,根据排序不等式,这个东西就是 i=1nτ2(i)1π2nlog3n+o(nlog2n)​​

    Loj 6539. 奇妙数论题

  14. 简要题意:求 i=1nj=1np=1njq=1nj[(i,j)=1][(p,q)=1]

    n2×109

    简要题意:注意到后面的式子像是在枚举 gcdj​ 的二元组 (p,q),我们按照这个思路化简式子

    i=1nj=1np=1nq=1n[(i,j)=1][(p,q)=j]i=1np=1nq=1n[(i,p,q)=1]​​​,这个式子我们就很熟了

    容易得到 d=1nμ(d)nd3,这个东西可以直接数论分块加杜教筛,复杂度仍然是 O(n23)

    Luogu P6055 [RC-02] GCD

  15. 简要题意:给定 nm,有 m 次操作,每次操作要么给出 x,y,z,对于所有 (i,x)=yai 加上 z,要么给定 x,查询 i=1xai

    n,m5×104

    简要题解:我们考虑对于位置 k​​,我们的加上 z[(k,x)=y]​,按照莫反的套路得到 zd|xy,dy|xμ(d)

    我们考虑枚举 xy 的约数,然后对于所有 dy 的倍数都加上 zμ(d),我们可以将倍数增加,改成单点加,这样我们在查询的时候需要查询约数和,这里的复杂度为 O(nlogn)

    那么前缀和的形式变成了 i=1xxiai,我们数论分块,复杂度仍然是 O(nlogn)

    总的时间复杂度 O(nnlogn),似乎有 O(nnlogn)​ 的做法

    hdu 4947 GCD Array

  16. 简要题意:求 i=1nj=1n[i,j](i,j)mod104857601

    n106

    简要题解:i=1nj=1n[i,j](i,j)=(n!)2nt=1n(t2i=1ntφ(i)1))2

    转指数上 是常见套路

    可以做到预处理 O(n),单次 O(nlogn)

    Luogu P5221 Product

  17. 简要题意:给定 m,每次随机选择一个 1m 的整数,与手上的数取 gcd,求期望多少次手上的数变成 1

    m105

    简要题解:令 fn​ 表示 n​ 变成 1​ 的期望次数,容易得到 fn=1+1md|nf(d)i=1m[(i,n)=d]

    这个式子拿莫反变一下能够得到 fn=1+1mT|nmTt|Tftμ(Tt)​​,后面的那个东西我们令其为 gn

    然后我们在求 fn​ 的时候只需要枚举约数即可,需要注意要把 fn​ 提出来,算完 fn​ 再更新 gn​ 即可时间复杂度 O(nlogn)

    CF 1139D Steps to One

  18. 简要题意:给定 n​​,求 x=1nd|xdτ(d)t|d(t+1)2​​

    m2.5×109

    简要题解:我们首先对 dτ(d) 下手,注意到该式等价于 t|dd=t|dtdt=(t|dt)2,这个变换再次展示了 的巨大区别 = =

    那么我们现在的式子就是 x=1nd|xt|dt2(t+1)2​​​​,我们变换一下次序,容易得到 d=1n(d2(d+1)2)i=1ndndi​​​​,指数上那个东西我们可以看成函数 f(n)=i=1nni=i=1nτ(i)​​​​​,那么答案就是这个东西 d=1n(d2(d+1)2)f(nd)​​​​,暴力算的话数论分块套数论分块的复杂度是 O(n34) 的,不能通过此题,但我们预处理 f 的前 n23 项就能做到 O(n23)

    总的时间复杂度为 O(nlogn+n23)

    Luogu 「EZEC-3」四月樱花

  19. 简要题意:给定 n,m,p,q,对于一个长度为 n 的序列 aiai 的每一位都是 [1,m],如果整个序列的 gcd 小于等于 q,且整个序列的 lcm 大于等于 p,那么这个序列是合法的,每个合法序列的价值是 i=1nai,求所有合法序列的价值的和

    n998244351,p,qm2×105

    简要题解:注意到一个序列的 gcd 一定是 lcm 的约数,所以我们考虑直接求 gk 表示 gcd1lcmk 的合法序列的价值的和,这样我们再搞一个调和级数的枚举就能求出所有合法的 gx,y

    对于 gk,显然我们不太好直接操作,我们考虑求 fk=d|kgd,即求 gcd1,且 lcmk 的约数的合法序列的价值的和,我们尝试列一下 fk 的式子

    fk=i1=1mi2=1min=1m[(i1,i2,,in)=1][[i1,i2,,in]|k]j=1nij=d|kμ(d)(d|i,i|ki)n=d|kμ(d)(dσ(kd))n=d|kμ(d)dnσn(kd)

    显然这个东西我们可以用调和级数的做法算出 f1fm,然后用作经典的莫比乌斯反演,我们能算出 gk,但是现在我们注意到我们只计算了 lcm 小于等于 m 的情况,但题目实际要求 lcm 大于等于 p 的情况,正难则反,我们求出只有 gcd 的要求下的所有答案,简单 lcm 小于 p 的即可,所有东西的 n 次方都可以预处理,时间复杂度 O(nlogn)

    The 2021 CCPC Guangzhou Onsite K Magus Night

  20. 简要题意:给定 n,求 1ni=1nf(i),其中 f(x) 是积性函数,且 f(pk)=pkk,答案对质数 4179340454199820289 取模

    n1012

    简要题解:看到 f(pk) 的式子,容易想到 min25,但是 1012 加上需要用龟速乘导致 min25 等一类亚线性筛跑不动,我们考虑 PN 筛,构造函数 g(x)=x,可以求得 h(pk)=pkk×(k1)g(x) 的前缀和可以 O(1) 求,那么我们的时间复杂度为 O(n)

    2022杭电多校6 B Jo loves counting

  21. 简要题意:现在有 T 次询问,每次询问给定 n,mi=1nj=1mφ(ij)

    T104,n,m105

    简要题解:我们根据 φ(ab)=φ(a)φ(b)(a,b)φ((a,b)),根据这个化简我们可以得到 T=1nt|Ttφ(t)μ(Tt)f(T,nT)f(T,mT),其中 f(x,y)=i=1yφ(ix),注意到所有合法的 f(x,y) 都满足 xyn,那么总共只有 O(nlogn)f(x,y),且可以 O(nlogn) 预处理

    但是只预处理 f(x,y) 我们依次询问也只能做到 O(n),不能通过此题

    我们考虑预处理 f(x,y)f(x,z) 的前缀和,我们只预处理 f(x,y)f(x,z),y,zB 的前缀和,这一部分的时间复杂度大概是 O(nBlogn) 的,那么在询问的时候我们考虑对于 ni>Bi 暴力算,这样的 i 只有 nB 个,求一次的时间复杂度为 O(1),那么总的时间复杂度为 O(nBlogn+T(nB+n),我们取 B50 左右可以通过此题

    Luogu P4240 毒瘤之神的考验

  22. 简要题意:给定 n,p,求 i=1nj=1n(i,j)(i,j)

    n1.5×106

    简要题解:经过简单的式子化简,我们可以得到 ans=T=1nt|Tμ(Tt)f2(tT,nT),其中 f(x,y)=i=1yxi

    我们考虑直接枚举 T,t 这个东西的时间复杂度是 O(nlogn)f(x,y) 显然是一个等比数列求和东西,我们直接套用等比数列求和的公式的话的时间复杂度为 O(logp),总的时间复杂度为 O(nlognlogp)

    但是我们注意到 tT 的前缀和最多才到 nT 项,如果我们计算这部分的时间复杂度是 O(lognT) 应该能显著减少常数,同时我想起来等比数列前缀和(n项)有 O(logn) 的做法,然后我们把这个做法套上去,发现这样就过了

    但其实 O(i=1nj=1nilog(nij)=O(nlogn),感觉非常神奇

    Luogu P6825 「EZEC-4」求和

  23. 简要题意:给定一个长度为 n 的序列 ai,求 max1i<jnlcm(ai,aj)

    n,ai105

    简要题解:注意到 ai 的值域很小,我们考虑一个针对值域的做法,首先我们把所有 ai 的约数都求出来,令其为集合 S,那么最终的答案一定为从 S 中选出两个互质的数的最大 lcm,我们考虑二分 lcm,那么如果 xSyS[(x,y)=1][xylcm],按照莫比乌斯反演的套路,我们得到 dSμ(d)d|xd|y[xylcm],我们枚举 d,后面枚举 x 之后是一个双指针,总时间复杂度为 O(nlog2n)

    其实这题还有一个 O(nlogn) 的做法,我们还是考虑对 Slcm,我们维护一个栈,从大到小加入数 x,如果栈中存在一个 yx 互质,那么对于 x<z<yz 一定没用了,因为我们现在的答案至少是 xy,而后面加入的数 wz 的答案至多是 wz<xy,所以我们可以一直弹栈顶直到栈中不存在与 x 互质的数,那么我们如何判断是否存在于 x 互质的数呢?答案还是莫反,我们有 yS[(x,y)=1]=d|xμdcntd,其中 cntd 表示有多少数是 d 的倍数,这个东西可以在入栈和出栈时顺便维护,时间复杂度 O(nlogn)

    CF 1285F Classical?

  24. 简要题意:给定两个长度为 n 的序列 ai,bi,求长度为 n 的序列 ci,其中 ck=maxgcd(i,j)=k|aibj|

    n105,ai,bi109

    简要题解:我们考虑只统计 aibj 的答案,对于 ai>bj 的答案我们只需要交换 ab 重新求一次即可,另外我们只考虑 gcd(i,j)=1 的情况,对于 gcd(i,j)=d 的情况,我们只需要将 ij 都除掉 d 即可

    首先我们将 a 按升序排序,b 按降序排序,那么我们考虑维护一个当前有效 b 的集合 S,我们当前枚举到 ai,我们考察集合 S 中是否有与 ai 互质的 bj,如果存在这么一个 bj,那么集合内所有小于 bj 的数都没有用了,原因我们可以这样考虑对于我们接下来枚举到的 ai>ai,其与 bj<bj 所组成的答案一定小于 aibj 组成的答案,那么我们的做法就是每次删除 S 中与 ai 互质的数 bj 以及小于 bj 的数,注意到我们在一开始就完成了所有 bj 的插入,所以我们可以维护一个栈来代替集合,至于如何判断是否存在与 ai 互质的数,通过莫反,我们发现只需要 cntdcntd 表示 S 中是 d 的倍数的个数

    时间复杂度 O(nlog2n),似乎还有比较好想的 O(nlog3n) 的二分做法

    2018-2019 Summer Petrozavodsk Camp, Oleksandr Kulkov Contest 2 B Yet Another Convolution

  25. 简要题意:给定 n,求 i=1nj=1ngcd(fib(i),fib(j))

    n1010

    简要题解:我们知道 gcd(fib(i),fib(j))=fib(gcd(i,j)),那么我们容易化简得到 ans=t=1nfib(t)i=1ntj=1nt[(i,j)=1],后面那两个 ,如果我们套用传统的 μ 去化简的话是不容易处理的,但我们注意到 的上指标相同,能够想起一个经常被遗忘的式子 i=1nj=1n[(i,j)=1]=2i=1nφ(i)1,

    我们令 S(n) 表示 φ 的前缀和,那么原式就是 i=1nfib(i)S(ni),相当于是一个数论分块套杜教筛,时间复杂度为 O(n23)

    The Hangzhou Normal U Qualification Trials for ZJPSC 2021 B Baom and Fibonacci

  26. 简要题意:给定一个长度为 n 的序列 ai 和两个整数 XY,求有多少数对 (i,j) 满足存在一个整数 v,使得 (v,ai)=X,同时 [v,aj]=Y

    n2×105,ai,X,Y1018

    简要题解:我们考虑如果存在一个数对,那么一定满足 X|Y,X|ai,aj|Y,我们令 S 表示 Y 的素数集合,然后我们对于每个素数单独考虑,对于一个素数 pS,我们令 cx 表示 X 的次数,cy 表示 y 的次数,ci 表示 ai 的次数,cj 表示 aj 的次数,那么对于 cx=cy 的情况我们一定可以选出一个 v,对于 cx<cy,通过讨论我们发现,ci=cxcj=cy 两者必须至少满足一个我们才能找到合法的 v

    另外我们发现 1018 范围内的数最多只有 15 个质因子,我们状压一下,相当于求 ST=UfSgT,这个东西拿高维前缀和求一下即可,时间复杂度 O(V14+21515)

    CF 1016G Appropriate Team

  27. 简要题意:给定一个长度为 n 的序列 ai,求 i=1nj=1nφ(gcd(ai,aj3))

    n3×105,ai[1,n]

    简要题解:我们直接化简

    i=1nj=1nφ(gcd(ai,aj3))=t=1nφ(t)i=1nj=1n[(ai,aj3)=t]=t=1nφ(t)i=1nj=1n[(ait,aj3t)=1]=t=1nφ(t)i=1nj=1nd|(ait,aj3t)μ(d)=t=1nφ(t)d=1ntμ(d)(d|ai)(d|aj3)

    注意到我们只需要预处理 d|aid|ai3 即可,后面那个东西本质和前面的一样,时间复杂度 O(nlogn)

    牛客 contest 43058E 炫酷反演魔术

  28. 简要题意:给定 l,r,求 i=lrf(i),其中 f(i) 表示 i 的非严格次大质因数,例如 f(1)=1,f(32)=3

    l,r1011

    简要题解:我们考察 min_25 的过程,发现在求 S(n,m) 的时候,我们枚举最小质因子 pke,k>m 时,如果这个 p 有贡献,那么说明剩下数字是质数,那么我们需要 g(npke,k),这些都可以在 min_25 的时候求出

    uoj 188 【UR #13】Sanrd