积性函数学习笔记

数论分块

对于形如

i=1nf(i)g(ni)

的式子,我们可以发现 ni 的值可以分成若干块,具体的,设上一块的右边界为 r,则当前块的左边界 l=r+1,右边界 r=nnl。块数为 O(n) 量级。

code:

LL S(LL n) {
  LL s = 0;
  for (LL l = 1, r; l <= n; l = r + 1) {
    r = n / (n / l);
    s += (SumF(r) - SumF(l - 1)) * G(n / l);
  }
  return s;
}

扩展:

多维数论分块

如果式子形如

i=1nf(i)g(a1i,a2i,,aki)

在取总块右边界的时候把 k 个块的右边界取 min 即可。块的量级为 O(ka)

LL S(LL n) {
  LL s = 0;
  for (LL l = 1, r; l <= n; l = r + 1) {
    r = INT64_MAX;
    for (int i = 1; i <= k; ++i) {
      r = min(r, a[i] / (a[i] / l));
    }
    s += (SumF(r) - SumF(l - 1)) * G(a[1] / l, a[2] / l, ..., a[k] / l);
  }
  return s;
}

多维嵌套数论分块

式子形如

Sk(n)=i=1ngk(i)Sk1(ni)S0(n)=f(n)

直接递归,总块数量级为 O(n12k)

LL S(LL n, int k) {
  if (k == 0) {
    return F(n);
  }
  LL s = 0;
  for (LL l = 1, r; l <= n; l = r + 1) {
    r = n / (n / l);
    s += (SumG(r, k) - SumG(l - 1, k)) * S(n / l, k - 1);
  }
  return s;
}

积性函数

定义

如果一个数论函数 f(n) 满足对于所有 gcd(i,j)=1,有 f(ij)=f(i)f(j),那么 f(n) 被称为积性函数。

特别的,如果对于所有 i,j 都有 f(ij)=f(i)f(j),那么 f(n) 被称为完全积性函数。

性质

如果 f(n)g(n) 都是积性函数,那么下列函数也是积性函数:

h(x)=f(xp)h(x)=f(x)ph(x)=f(x)g(x)h(x)=dxf(d)g(x/d)

常见积性函数

  • 单位函数 ϵ(n)=[n=1]完全积性函数
  • 幂函数 idk(n)=nkid1 一般简记为 id完全积性函数
  • 常数函数 1(n)=1,也记作 I完全积性函数
  • 因数个数函数 d(n)=dn1=d=1n[dn]
  • 除数函数 σk(n)=dndkk=1 时为因数和函数,k=0 时为因数个数函数。
  • 欧拉函数 φ(n)=i=1n[gcd(i,n)=1]
  • 莫比乌斯函数 μ(n),设 n=i=1kpiei,那么有 μ(n)={1if n=10if ei>1(1)kotherwise.

线性筛

我们在小学二年级就知道线性筛可以在 O(n) 的时间内筛出 n 的质数,但其实它还可以筛积性函数。我们只要知道积性函数 f 在质数的幂处的取值,就能用线性筛筛出 f

f[1] = 1;
for (int i = 2; i <= n; ++i) {
  if (!v[i]) {
    p.push_back(i), f[i] = /*f 在质数 i 处的取值*/;
    sp[i] = i, bp[i] = i, kp[i] = 1;
  }
  for (int j : p) {
    int k = i * j;
    if (k > n) {
      break;
    }
    v[k] = 1;
    if (i % j) {
      f[k] = f[i] * f[j];
      sp[k] = j, bp[k] = j, kp[k] = 1;
    } else {
      if (sp[i] == i) {
        f[k] = /*f 在质数的幂 bp[i]^(kp[i]+1)=k 处的取值*/;
      } else {
        f[k] = f[i / sp[i]] * f[j * sp[i]];
      }
      sp[k] = sp[i] * j, bp[k] = bp[i], kp[k] = kp[i] + 1;
      break;
    }
  }
}

狄利克雷卷积

定义

对于两个数论函数 f,g,定义它们的狄利克雷卷积为:

(fg)(n)=dnf(d)g(n/d)

性质

  1. 满足交换律、结合律、分配律。
  2. ϵ 为狄利克雷卷积的单位元,即有 (fϵ)(n)=dnf(d)ϵ(n/d)=f(n)
  3. μ 为狄利克雷卷积中 1 的逆元,即 f1=hf=hμ
  4. f,g 为积性函数,则 fg 为积性函数。
  5. ϵ=μ1=dnμ(d)
  6. 1idk=σk
  7. φ1=idφ=μid

狄利克雷(前/后)缀(和/差分)

我们经常会遇到求 f1fμ 的前缀和这类的问题。虽然可以手动分析,但有时候却分析不出来。这时候就要用到狄利克雷前缀和(或其他的)了。

以下讲解的是狄利克雷前缀和,等价于卷 1,其他情况类似,差分等价于卷 μ

它的本质是做多维前缀和,即对每个质数 p,把 fp 加到 fip 上。正确性可以感性理解。

模板题:P5495 Dirichlet 前缀和

前缀和:

for (int i : p) {
  for (int j = 1; i * j <= n; ++j) {
    f[i * j] += f[j];
  }
}

后缀和(实际上是做倍数卷积,即 g(n)=ndf(d)):

for (int i : p) {
  for (int j = n / i; j >= 1; --j) {
    f[j] += f[i * j];
  }
}

前缀差分:

for (int i : p) {
  for (int j = n / i; j >= 1; --j) {
    f[i * j] -= f[j];
  }
}

后缀差分(实际上是做倍数卷积,即 g(n)=ndμ(d/n)f(d)):

for (int i : p) {
  for (int j = 1; i * j <= n; ++j) {
    f[j] -= f[i * j];
  }
}

杜教筛

题目类型

S(n)=i=1nf(i),其中 f 是积性函数。

算法解决

显然可以线性筛,时间复杂度 O(n),不够优秀。

考虑构造积性函数 h,g,使得 fg=h

那么有:

i=1nh(i)=i=1ndif(i/d)g(d)=d=1ng(d)dif(i/d)=d=1ng(d)i=1ndf(i)=d=1ng(d)S(nd)

S(n) 单独拎出来,有:

S(n)=i=1nh(i)d=2ng(d)S(nd)g(1)

于是我们只要能做到快速计算 hg 的前缀和即可。记忆化实现,时间复杂度 O(n3/4);线性筛预处理 n2/3 的部分可以做到 O(n2/3)

以下是实现:

φ(i) 的前缀和

φ1=id,代码实现如下:

LL Sphi(int n) {
  if (n < kM) {
    return phi[n];
  }
  auto p = fphi.find(n);
  if (p != fphi.end()) {
    return p->second;
  }
  auto &f = fphi[n];
  f = 1LL * n * (n + 1) / 2;
  for (LL l = 2, r; l <= n; l = r + 1) {
    r = n / (n / l);
    f -= (r - l + 1) * Sphi(n / l);
  }
  return f;
}

μ(i) 的前缀和

μ1=ϵ,代码实现如下:

LL Smu(int n) {
  if (n < kM) {
    return mu[n];
  }
  auto p = fmu.find(n);
  if (p != fmu.end()) {
    return p->second;
  }
  auto &f = fmu[n];
  f = 1;
  for (LL l = 2, r; l <= n; l = r + 1) {
    r = n / (n / l);
    f -= (r - l + 1) * Smu(n / l);
  }
  return f;
}

P4213 【模板】杜教筛(Sum) 代码:

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;
using LL = long long;

const int kM = 1664511;

int t, n;
LL phi[kM], mu[kM];
bool v[kM];
vector<LL> p;
unordered_map<LL, LL> fphi, fmu;

LL Sphi(LL n) {
  if (n < kM) {
    return phi[n];
  }
  auto p = fphi.find(n);
  if (p != fphi.end()) {
    return p->second;
  }
  auto &f = fphi[n];
  f = n * (n + 1) / 2;
  for (LL l = 2, r; l <= n; l = r + 1) {
    r = n / (n / l);
    f -= (r - l + 1) * Sphi(n / l);
  }
  return f;
}
LL Smu(LL n) {
  if (n < kM) {
    return mu[n];
  }
  auto p = fmu.find(n);
  if (p != fmu.end()) {
    return p->second;
  }
  auto &f = fmu[n];
  f = 1;
  for (LL l = 2, r; l <= n; l = r + 1) {
    r = n / (n / l);
    f -= (r - l + 1) * Smu(n / l);
  }
  return f;
}

int main() {
  ios_base::sync_with_stdio(0), cin.tie(0);
  phi[1] = mu[1] = 1;
  for (LL i = 2; i < kM; ++i) {
    if (!v[i]) {
      phi[i] = i - 1, mu[i] = -1;
      p.push_back(i);
    }
    for (LL j : p) {
      if (i * j >= kM) {
        break;
      }
      v[i * j] = 1;
      if (i % j) {
        phi[i * j] = phi[i] * phi[j], mu[i * j] = mu[i] * mu[j];
      } else {
        phi[i * j] = phi[i] * j, mu[i * j] = 0;
        break;
      }
    }
  }
  for (LL i = 2; i < kM; ++i) {
    phi[i] += phi[i - 1], mu[i] += mu[i - 1];
  }
  for (cin >> t; t--; ) {
    cin >> n;
    cout << Sphi(n) << ' ' << Smu(n) << '\n';
  }
  return 0;
}

莫比乌斯变换/反演

常见反演形式

形式一

[x=1]=dxμ(d),即 ϵ=μ1

更常见的形式是 [gcd(i,j)=1]=dgcd(i,j)μ(d)=didjμ(d)

形式二

如果有

f(n)=dng(d)

(即 f=g1

那么有

g(n)=dnμ(d)f(n/d)

(即 g=fμ

形式三

如果有

f(n)=ndg(d)

那么有

g(n)=ndμ(d/n)f(d)

常见反演套路

以下默认 nm

形式一

i=1nj=1mf(gcd(i,j))=d=1nf(d)i=1nj=1m[gcd(i,j)=d]=d=1nf(d)i=1n/dj=1m/d[gcd(di,dj)=d]=d=1nf(d)i=1n/dj=1m/d[gcd(i,j)=1]=d=1nf(d)i=1n/dj=1m/dpipjμ(p)=d=1nf(d)p=1n/dμ(p)i=1n/dpj=1m/dp1=d=1nf(d)p=1n/dμ(p)n/dpm/dp

t=dp,则

d=1nf(d)p=1n/dμ(p)n/dpm/dp=d=1nf(d)t=1,dtnμ(t/d)n/tm/t=t=1nn/tm/tdtf(d)μ(t/d)=t=1nn/tm/t(fμ)(t)

可以手动分析 fμ,也可以无脑预处理然后数论分块,后一种的时间复杂度为 O(nloglogn)O(n)

例题

PGCD - Primes in GCD Table

题意

i=1nj=1m[gcd(i,j) is a prime]

思路

以下设 nm

直接套上面的套路即可。

i=1nj=1m[gcd(i,j) is a prime]=t=1nn/tm/tdt[d is a prime]μ(t/d)

可以发现后面的东西可以线性筛,时间复杂度 O(n+tn)

多倍经验:P2257 YY的GCDP2568 GCD

GCDMAT - GCD OF MATRIX

题意

i=i1i2j=j1j2gcd(i,j)

思路

以下设 nm

S(n,m)=i=1nj=1mgcd(i,j)

直接套上面的式子得:

S(n,m)=i=1nnimi(idμ)(i)=i=1nnimiφ(i)

线性筛后数论分块即可,答案为 S(i2,j2)S(i2,j11)S(i11,j2)+S(i11,j11)

P1447 [NOI2010] 能量采集

题意

i=1nj=1m2gcd(i,j)1

思路

显然有

i=1nj=1m2gcd(i,j)1=2(i=1nj=1mgcd(i,j))nm

直接套上面的式子即可。

P1390 公约数的和

题意

i=1nj=i+1ngcd(i,j)

思路

i=1nj=i+1ngcd(i,j)=(i=1nj=1ngcd(i,j))n(n+1)22

直接套上面的式子即可。

LCMSUM - LCM Sum

题意

i=1nlcm(i,n)

思路

i=1nlcm(i,n)=i=1ningcd(i,n)=ni=1nigcd(i,n)=nd=1ni=1nid[gcd(i,n)=d]=ndni=1n/di[gcd(i,n/d)=1]

发现后面那堆东西意义是与 n/d 互质的数的和,即 n/dφ(n/d)2,线性筛后枚举 d 对倍数转移预处理即可。

注:注意特判 n/d=1 的情况。

P3327 [SDOI2015]约数个数和

题意

i=1nj=1md(ij)

思路


首先需要知道约数个数函数 d 的一个性质:

d(ij)=xiyj[gcd(x,y)=1]

证明:

x 的质因数分解中的一项 pay 对应的 pb,因为 x,y 互质,故必有一项为 p0

  • b=0:则对应的 ij 的因子的对应项为 pa
  • a=0:设 i 的对应项为 pk,则对应的 ij 的因子的对应项为 pk+b

容易发现这种表示方法不重。故得证。


以下设 nm

由性质有

i=1nj=1md(ij)=i=1nj=1mxiyj[gcd(x,y)=1]=x=1ny=1mn/xm/y[gcd(x,y)=1]=x=1ny=1mn/xm/ydx,dyμ(d)=d=1nμ(d)dxnn/xdymm/y=d=1nμ(d)x=1n/dn/d/xy=1m/dm/d/y

预处理 i=1nn/i 后数论分块即可。

P5221 Product

题意

i=1nj=1nlcm(i,j)gcd(i,j)

思路

原式即为

i=1nj=1nijgcd(i,j)2

由于 的优秀性质,我们可以把这个式子拆成两部分:

i=1nj=1nij(i=1nj=1ngcd(i,j))2

分子部分

i=1nj=1nij=i=1ninn!=(n!)n(n!)n=(n!)2n

分母部分

i=1nj=1ngcd(i,j)=d=1ni=1nj=1n[gcd(i,j)=d]d=d=1ndi=1nj=1n[gcd(i,j)=d]

看指数部分,有:

i=1nj=1n[gcd(i,j)=d]=i=1n/dj=1n/d[gcd(i,j)=1]=2i=1n/dj=1i[gcd(i,j)=1]1=2i=1n/dφ(i)1

预处理 φ 前缀和即可。

注意指数部分是对 1048576011=104857600 取模。

P6055 [RC-02] GCD

题意

i=1nj=1np=1n/jq=1n/j[gcd(i,j)=1][gcd(p,q)=1]

思路

i=1nj=1np=1n/jq=1n/j[gcd(i,j)=1][gcd(p,q)=1]=i=1nj=1np=1nq=1n[gcd(i,j)=1][gcd(p,q)=j]=i=1np=1nq=1n[gcd(i,p,q)=1]=i=1np=1nq=1ndi,dp,dqμ(d)=d=1nμ(d)didpdq1=d=1nμ(d)nd3

杜教筛求 μ 的前缀和即可,时间复杂度 O(n2/3)


数论分块套杜教筛复杂度证明:

可以发现由于杜教筛内部是用数论分块实现的,所以只要筛一次 n,就会把数论分块要用到的值全部筛出来,时间复杂度为 O(n2/3+n1/2)=O(n2/3)


P3768 简单的数学题

题意

(i=1nj=1nijgcd(i,j))modp

思路

i=1nj=1nijgcd(i,j)=d=1nd3i=1nj=1n(i/d)(j/d)[gcd(i,j)=d]=d=1nd3i=1n/dj=1n/dij[gcd(i,j)=1]=d=1nd3i=1n/dj=1n/dijpi,pjμ(p)=d=1nd3p=1nμ(p)i=1,pin/dij=1,pjn/dj=d=1nd3p=1nμ(p)(i=1,pin/di)2

S(n)=n(n+1)2。有

d=1nd3p=1nμ(p)(i=1,pin/di)2=d=1nd3p=1nμ(p)(pi=1,pin/di/p)2=d=1nd3p=1nμ(p)p2(i=1n/dpi)2=d=1nd3p=1nμ(p)p2S(n/dp)2

t=dp,有

d=1nd3p=1nμ(p)p2S(n/dp)2=t=1nS(n/t)2d=1,dtnd3μ(t/d)(t/d)2=t=1nS(n/t)2d=1,dtndμ(t/d)t2=t=1nS(n/t)2t2d=1,dtndμ(t/d)=t=1nS(n/t)2t2φ(t)

注意到 n2φ(n)id2=id3,可以使用杜教筛。


关于如何发现上面那个式子。

首先直接设 n2φ(n)f(n)=g(n),展开有

g(n)=dnd2φ(d)f(n/d)

我们知道 φ1=id,所以想办法把 d2 消掉,于是自然想到了 f=id2

于是有

g(n)=dnd2φ(d)(n/d)2=n2dnφ(d)=n2n=n3


P3172 [CQOI2015]选数

题意

a1=LRa2=LRan=LR[gcdi=1nai=k]

思路

l=L/k,r=R/k,有

a1=LRa2=LRan=LR[gcdi=1nai=k]=a1=lra2=lran=lr[gcdi=1nai=1]=a1=lra2=lran=lrdaiμ(d)=d=1rμ(d)a1=l,da1ra2=l,da2ran=l,danr1=d=1rμ(d)(r/d(l1)/d)n

杜教筛维护前缀和,数论分块即可。

P4449 于神之怒加强版

题意

i=1nj=1mgcd(i,j)k

109+7 取模的结果。

思路

直接套式子得:

t=1nn/tm/tdtdkμ(t/d)

后面那坨东西做个狄利克雷前缀差分就好了。

P6825 「EZEC-4」求和

题意

i=1nj=1ngcd(i,j)i+j

p 取模的值。

思路

i=1nj=1ngcd(i,j)i+j=d=1ni=1n/dj=1n/ddd(i+j)[gcd(i,j)=1]=d=1ni=1n/dj=1n/ddd(i+j)pi,pjnμ(p)=d=1np=1n/dμ(p)i=1n/dpj=1n/dpddp(i+j)

t=dp,有

d=1np=1n/dμ(p)i=1n/dpj=1n/dpddp(i+j)=d=1np=1n/dμ(p)i=1n/tj=1n/tdt(i+j)=d=1np=1n/dμ(p)i=1n/t(dt)ij=1n/t(dt)j=d=1np=1n/dμ(p)(i=1n/t(dt)i)2

S(b,n)=i=1nbi=bn+1bb1,特别的,当 b=1 时,S(1,n)=n

那么原式就是

d=1np=1n/dμ(p)S(dt,n/t)2

直接暴力算即可,时间复杂度 O(nlogn)

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

题意

i=1nj=1mlcm(i,j)

20101009 取模的值。

思路

以下设 nm

i=1nj=1mlcm(i,j)=i=1nj=1mijgcd(i,j)=d=1ni=1nj=1mijd[gcd(i,j)=d]=d=1ni=1n/dj=1m/ddij[gcd(i,j)=1]=d=1ndi=1n/dj=1m/dijpi,pjμ(p)=d=1ndp=1n/dμ(p)p2i=1n/dpj=1m/dpij

S(n)=i=1ni=n(n+1)2,t=dp,有

d=1ndp=1n/dμ(p)p2i=1n/dpj=1m/dpij=d=1ndp=1n/dμ(p)p2S(n/t)S(m/t)=t=1ndtdμ(t/d)(t/d)2S(n/t)S(m/t)=t=1ntS(n/t)S(m/t)dtμ(t/d)(t/d)=t=1ntS(n/t)S(m/t)dtμ(d)d

看后面那部分 f(n)=dnμ(d)d,显然有 f(p)=1pf(pk)=f(p)=1p,于是可以线性筛预处理后整除分块。

P6156 简单题

题意

i=1nj=1n(i+j)kμ2(gcd(i,j))gcd(i,j)

998244353 取模的值。

思路

地狱绘图

i=1nj=1n(i+j)kμ2(gcd(i,j))gcd(i,j)=d=1ni=1nj=1n(i+j)kμ2(d)d[gcd(i,j)=d]=d=1nμ2(d)di=1nj=1n(i+j)k[gcd(i,j)=d]=d=1nμ2(d)di=1n/dj=1n/d(di+dj)k[gcd(i,j)=1]=d=1nμ2(d)dk+1i=1n/dj=1n/d(i+j)kpi,pjμ(p)=d=1nμ2(d)dk+1p=1n/dμ(p)pki=1n/dpj=1n/dp(i+j)k

fidk 的前缀和,gf 的前缀和,S(n)=i=1nj=1n(i+j)k,有

S(n)=i=1nf(n+i)f(i)=g(2n)g(n)g(n)=g(2n)2g(n)

于是有

d=1nμ2(d)dk+1p=1n/dμ(p)pki=1n/dpj=1n/dp(i+j)k=d=1nμ2(d)dk+1p=1n/dμ(p)pkS(n/dp)

t=dp,有

d=1nμ2(d)dk+1p=1n/dμ(p)pkS(n/t)=t=1nS(n/t)dtμ2(d)dk+1μ(t/d)(t/d)k=t=1nS(n/t)tkdtdμ2(d)μ(t/d)

h(n)=dndμ2(d)μ(n/d),由于它是若干个积性函数卷起来,所以也是积性函数,因此我们分类讨论 h(pk) 即可。

  1. k=1:此时,h(p)=μ(p)+pμ2(p)=p1
  2. k=2:此时,h(p2)=μ(p2)+pμ2(p)μ(p)+p2μ2(p2)=p
  3. k>2:此时,对于 h(pk) 中的任意一项 piμ2(pi)μ(pki),都有 i2ki2,故 f(pk)=0

这时,我们就能用线性筛预处理 hidk。然后数论分块即可。

改一下可以过 P6222 「P6156 简单题」加强版

P7486 「Stoi2031」彩虹

题意

i=lrj=lrlcm(i,j)lcm(i,j)

32465177 取模的值。

思路

f(n,m)=i=1nj=1mlcm(i,j)lcm(i,j),答案显然为 f(r,r)f(l1,l1)f(r,l1)f(l1,r),由于 f(n,m)=f(m,n),以下不妨设 nm

f(n,m)=i=1nj=1mlcm(i,j)lcm(i,j)=i=1nj=1mijgcd(i,j)ijgcd(i,j)=d=1ni=1nj=1mijdijd[gcd(i,j)=d]=d=1ni=1n/dj=1m/dijdijd[gcd(i,j)=1]=d=1ni=1n/dj=1m/dijdijdpi,pjμ(p)=d=1ni=1n/dj=1m/dpi,pjijdijdμ(p)=d=1np=1n/di=1n/dpj=1m/dp(ijdp2)ijdp2μ(p)

t=dp,有

d=1np=1n/di=1n/dpj=1m/dp(ijdp2)ijdp2μ(p)=d=1np=1n/di=1n/tj=1m/t(ijtp)ijtpμ(p)=t=1npti=1n/tj=1m/t(ijtp)ijtpμ(p)=t=1n(pt(i=1n/tj=1m/t(ijtp)ij)pμ(p))t=t=1n(pt(i=1n/tj=1m/t(ij)iji=1n/tj=1m/t(tp)ij)pμ(p))t

S(n,m)=i=1nj=1m(ij)ijs(n)=i=1ni=n(n+1)2g(n)=i=1nii,有

S(n,m)=i=1nj=1m(ij)ij=i=1nj=1miijjij=i=1nj=1m(ii)ji=1nj=1m(jj)i=i=1n(ii)s(m)i=1ng(m)i=g(n)s(m)g(m)s(n)

另一边,我们有:

i=1nj=1mxij=xi=1nj=1mij=xs(n)s(m)

代入原式,得:

t=1n(pt(i=1n/tj=1m/t(ij)iji=1n/tj=1m/t(tp)ij)pμ(p))t=t=1n(pt(S(n/t,m/t)(tp)s(n/t)s(m/t))pμ(p))t=t=1n(ptS(n/t,m/t)pμ(p)ps(n/t)s(m/t)pμ(p)ts(n/t)s(m/t)pμ(p))t

h(n)=pnpμ(p)w(n)=dnddμ(d),有:

t=1n(ptS(n/t,m/t)pμ(p)ps(n/t)s(m/t)pμ(p)ts(n/t)s(m/t)pμ(p))t=t=1n(S(n/t,m/t)h(t)w(t)s(n/t)s(m/t)ts(n/t)s(m/t)h(t))t

再设 r(n)=(w(n)nh(n))n,有

t=1n(S(n/t,m/t)h(t)w(t)s(n/t)s(m/t)ts(n/t)s(m/t)h(t))t=t=1nS(n/t,m/t)h(t)tr(t)s(n/t)s(m/t)

至此,我们可以通过数论分块解决问题。

整理一下要用的函数:

  • s(n)=i=1ni=n(n+1)2:位于指数上,可 O(1) 计算,模 p1
  • g(n)=i=1nii:位于底数上,可 O(nlogn) 预处理,模 p
  • S(n,m)=g(n)s(m)g(m)s(n):位于底数上,可 O(logp) 计算,模 p
  • h(n)=pnpμ(p):积性函数,位于指数上,可 O(n) 预处理(线性筛),模 p1
  • w(n)=dnddμ(d):位于底数上,可以 O(nlogn) 预处理,模 p
  • r(n)=(w(n)nh(n))n:位于底数上,可以 O(logp) 直接计算,模 p

再整理一下要预处理的东西:

  • g(n)=i=1nii:直接预处理 ii 后前缀积。
  • h(n)=pnpμ(p):使用线性筛预处理,h(pk)=1p
  • w(n)=dnddμ(d):枚举 d 对倍数贡献即可。
  • h(t)t 的前缀和,对 p1 取模。
  • r(t) 的前缀积和逆元,对 p 取模。

P3704 [SDOI2017]数字表格

题意

i=1nj=1mfgcd(i,j)

109+7 取模的值。其中 f 是斐波那契数列。

思路

以下设 nm

i=1nj=1mfgcd(i,j)=d=1ni=1nj=1mfd[gcd(i,j)=d]=d=1nfdi=1nj=1m[gcd(i,j)=d]=d=1nfdi=1n/dj=1m/d[gcd(i,j)=1]=d=1nfdp=1n/dμ(p)n/dpm/dp

t=dp,有

d=1nfdp=1n/dμ(p)n/dpm/dp=d=1np=1n/dfdμ(p)n/tm/t=t=1n(dtfdμ(t/d))n/tm/t

F(n)=dnfdμ(n/d),则

t=1n(dtfdμ(t/d))n/tm/t=t=1nF(t)n/tm/t

F(t) 显然可以直接 O(n(logp+logn)) 预处理,数论分块即可。

GCDMAT2 - GCD OF MATRIX (hard)

题意

i=i1i2j=j1j2gcd(i,j)

109+7 取模的值。多组数据。

T5×104max(i2),max(j2)106

思路

为方便,以下 i1,j1 均为原 i11,j11

这道题目我们在之前已经见过一次了,设 S(n,m)=i=1nj=1mgcd(i,j),则 S(n,m)=i=1nφ(i)n/im/i,答案即为 S(i2,j2)S(i1,j2)S(i2,j1)+S(i1,j1)

但是这样常数太大,过不去。考虑优化。

首先可以发现 S(n,m) 是没必要的,我们直接看原式,设 n=min(i2,j2),有

i=i1+1i2j=j1+1j2gcd(i,j)=d=1ni=i1+1i2j=j1+1j2d[gcd(i,j)=d]=d=1ndi=(i1+1)/di2/dj=(j1+1)/dj2/d[gcd(i,j)=1]=d=1ndi=i1/d+1i2/dj=j1/d+1j2/dpi,pjμ(p)=d=1ndp=1n/dμ(p)i=i1/dp+1i2/dpj=j1/dp+1j2/dp1=d=1ndp=1n/dμ(p)(i2/dpi1/dp)(j2/dpj1/dp)

t=dp,有

d=1ndp=1n/dμ(p)(i2/dpi1/dp)(j2/dpj1/dp)=d=1ndp=1n/dμ(p)(i2/ti1/t)(j2/tj1/t)=t=1n(i2/ti1/t)(j2/tj1/t)pt(t/p)μ(p)=t=1nφ(t)(i2/ti1/t)(j2/tj1/t)

但是这样常数还是太大,过不去。

优化一:考虑预处理 1/n(浮点数下),把除法改成乘法,再逝当卡常就能过了

优化二:根号分治,设一个阈值 S,对于 tS,直接暴力算,对于 t>S,数论分块。

至此终于能过了。

P1587 [NOI2016] 循环之美

题意

求对于所有 1xn1ym,有多少最简分数 xy 满足 k 进制下的小数形式为纯循环小数。特别的,我们认为整数属于纯循环小数。

思路

首先显然要满足 gcd(x,y)=1。设 xy 的循环节位数为 l,那么有

{xy}={xkly}xyxy=xklyxklyxyxy=xklyxklyxxkl(mody)kl1(mody)gcd(k,y)=1

最后一步(xl1(modm)gcd(x,m)=1)的证明:

  • xl1(modm)gcd(x,m)=1:显然令 l=φ(m) 即可。
  • xl1(modm)gcd(x,m)=1:我们有 gcd(xl,m)=gcd(xl,xlmodm)=gcd(xl,1)=1,若 gcd(x,m)1,那么有 gcd(xl,m)1,矛盾,故 gcd(x,m)=1

此时式子就成了

i=1nj=1m[gcd(i,j)=1][gcd(j,k)=1]

求解这个式子即可。

我们有

i=1nj=1m[gcd(i,j)=1][gcd(j,k)=1]=i=1nj=1m[gcd(j,k)=1]pi,pjμ(p)=p=1min(n,m)μ(p)pinpjm[gcd(j,k)=1]=p=1min(n,m)μ(p)nppjm[gcd(j,k)=1]=p=1min(n,m)μ(p)np[gcd(p,k)=1]j=1m/p[gcd(j,k)=1]

f(n)=i=1n[gcd(i,k)=1],由于 gcd(i+k,k)=gcd(i,k),所以 gcd(i,k) 是有一个长度为 k 的循环节的,那么有

f(n)=f(nmodk)+n/kf(k)

这个式子是可以 O(klogk) 预处理后 O(1) 算的。

那么有

p=1min(n,m)μ(p)np[gcd(p,k)=1]j=1m/p[gcd(j,k)=1]=p=1min(n,m)f(m/p)npμ(p)[gcd(p,k)=1]

现在这个式子已经可以数论分块了,现在只剩预处理 i=1nμ(i)[gcd(i,k)=1] 的问题了。

我们设 S(n)=i=1nμ(i)[gcd(i,k)=1],那么有

S(n)=i=1nμ(i)[gcd(i,k)=1]=i=1n[gcd(i,k)=1]S(n/i)i=2n[gcd(i,k)=1]S(n/i)

只看前面部分,有

i=1n[gcd(i,k)=1]S(n/i)=i=1n[gcd(i,k)=1]j=1n/iμ(j)[gcd(j,k)=1]=i=1nj=1n/iμ(j)[gcd(ij,k)=1]=t=1n[gcd(t,k)=1]jtμ(j)=t=1n[gcd(t,k)=1][t=1]=1

于是有

S(n)=1i=2n[gcd(i,k)=1]S(n/i)

这个式子也可以数论分块。采用类似杜教筛的方法即可。

总时间复杂度为 O(klogk+n2/3),证明参考数论分块套杜教筛复杂度证明。

P3700 [CQOI2017]小 Q 的表格

题意

有一个表格 f(a,b),满足:

  • f(a,b)=f(b,a)
  • bf(a,a+b)=(a+b)f(a,b)

初始时 f(a,b)=ab

m 次操作,每次操作会将 f(ai,bi) 修改为 xi,同时,你需要修改此次操作涉及到的格子,使得操作后仍满足上面两条条件。每次询问后,你需要输出 x=1kiy=1kif(x,y),答案对 109+7 取模。

思路

首先有

bf(a,a+b)=(a+b)f(a,b)abf(a,a+b)=a(a+b)f(a,b)f(a,a+b)a(a+b)=f(a,b)ab

这是辗转相减法的形式,结合 f(a,b)=f(b,a),我们可以得到

f(a,b)=f(d,d)d2ab

其中 d=gcd(a,b)

于是我们只要维护 f(d,d) 即可。设 g(d)=f(d,d)

答案即为

i=1kj=1kf(i,j)=i=1kj=1kg(gcd(i,j))gcd(i,j)2ij=d=1kg(d)d2i=1kj=1kij[gcd(i,j)=d]=d=1kg(d)i=1k/dj=1k/dij[gcd(i,j)=1]=d=1kg(d)p=1k/dμ(p)p2i=1k/dpj=1k/dpij

S(n)=i=1ni=n(n+1)2,有

d=1kg(d)p=1k/dμ(p)p2i=1k/dpj=1k/dpij=d=1kg(d)p=1k/dμ(p)p2S(k/dp)2

h(n)=i=1nμ(i)i2S(n/i)2,有

h(n)h(n1)=i=1nμ(i)i2S(n/i)2i=1n1μ(i)i2S((n1)/i)2=inμ(i)i2(S(n/i)2S(n/i1)2)=inμ(i)i2(n/i)3=n2inμ(i)(n/i)=n2φ(n)

于是有

h(n)=i=1ni2φ(i)

原式即为

d=1kg(d)h(k/d)

树状数组维护 g(n) 的前缀和,数论分块即可。时间复杂度 O(mn)

P5518 [MtOI2019]幽灵乐团 / 莫比乌斯反演基础练习题

题意

i=1Aj=1Bk=1C(lcm(i,j)gcd(i,k))f(type)

其中 type{0,1,2},并且

f(0)=1f(1)=ijkf(2)=gcd(i,j,k)

答案对 p 取模。

思路

原式显然等于

i=1Aj=1Bk=1C(ijgcd(i,j)gcd(i,k))f(type)

由于 的优良性质,我们仅需要求解下列两个式子:

f1(a,b,c)=i=1aj=1bk=1cif(type)f2(a,b,c)=i=1aj=1bk=1cgcd(i,j)f(type)

答案即为

f1(a,b,c)f1(b,a,c)f2(a,b,c)f2(a,c,b)

f(0)=1

f1(a,b,c)=i=1aj=1bk=1cif2(a,b,c)=i=1aj=1bk=1cgcd(i,j)

对于 f1,有

f1(a,b,c)=i=1aj=1bk=1ci=i=1aibc=(a!)bc

预处理即可做到 O(logn) 计算。

对于 f2,设 n=min(a,b),有

f2(a,b,c)=i=1aj=1bk=1cgcd(i,j)=i=1aj=1bgcd(i,j)c=(d=1ndi=1aj=1b[gcd(i,j)=d])c=(d=1ndp=1n/dμ(p)a/dpb/dp)c=(d=1np=1n/ddμ(p)a/dpb/dp)c

t=dp,有

(d=1np=1n/ddμ(p)a/dpb/dp)c=(t=1n(dtdμ(t/d))a/tb/t)c

中间那部分显然可以 O(nlogn) 预处理,然后就可以数论分块+快速幂做到 O(nlogn)

f(1)=ijk

f1(a,b,c)=i=1aj=1bk=1ciijkf2(a,b,c)=i=1aj=1bk=1cgcd(i,j)ijk

对于 f1,有

f1(a,b,c)=i=1aj=1bk=1ciijk=(i=1aii)S(b)S(c)

其中 S(n)=i=1ni=n(n+1)2

可以 O(n) 预处理后 O(logn) 处理单次询问。

对于 f2,设 n=min(a,b),有

f2(a,b,c)=i=1aj=1bk=1cgcd(i,j)ijk=(i=1aj=1bgcd(i,j)ij)S(c)=(d=1ndi=1aj=1bij[gcd(i,j)=d])S(c)

先看指数,有

i=1aj=1bij[gcd(i,j)=d]=d2i=1a/dj=1b/dij[gcd(i,j)=1]=d2p=1n/dμ(p)p2i=1a/dpij=1b/dpj=d2p=1n/dμ(p)p2S(a/dp)S(b/dp)

代入原式,有

(d=1ndi=1aj=1bij[gcd(i,j)=d])S(c)=(d=1ndd2p=1n/dμ(p)p2S(a/dp)S(b/dp))S(c)=(d=1np=1n/ddd2μ(p)p2S(a/dp)S(b/dp))S(c)

t=dp,有

(d=1np=1n/ddd2μ(p)p2S(a/dp)S(b/dp))S(c)=(t=1n(dtdd2μ(t/d)(t/d)2)S(a/t)S(b/t))S(c)=(t=1n(dtdμ(t/d))t2S(a/t)S(b/t))S(c)

要预处理的东西和 type=0 差不多,数论分块可以做到 O(nlogn)

f(2)=gcd(i,j,k)

直接考虑原式,设 n=min(a,b,c),取 ln

i=1aj=1bk=1cln(lcm(i,j)gcd(i,k))gcd(i,j,k)=d=1nφ(d)i=1a/dj=1b/dk=1c/dln(lcm(i,j)gcd(i,k))

再取 exp

d=1n(i=1a/dj=1b/dk=1c/dlcm(i,j)gcd(i,k))φ(d)

可以发现中间部分就是 type=0 时的答案,数论分块套数论分块即可,时间复杂度 O(n3/4logn)

P4240 毒瘤之神的考验

题意

i=1nj=1mφ(ij)

998244353 取模的值,多组询问。

思路

神仙题。

以下设 nm

首先有一个经典结论:

φ(ij)φ(gcd(i,j))=φ(i)φ(j)gcd(i,j)

证明:

我们有

φ(ij)φ(gcd(i,j))=ijpipjp1gcd(i,j)pipjp1=gcd(i,j)ipip1jpjp1=gcd(i,j)φ(i)φ(j)

(第二步由容斥原理可得)

因此有

i=1nj=1mφ(ij)=i=1nj=1mφ(i)φ(j)gcd(i,j)φ(gcd(i,j))=d=1ndφ(d)i=1nj=1m[gcd(i,j)=d]φ(i)φ(j)=d=1ndφ(d)i=1n/dj=1m/d[gcd(i,j)=1]φ(id)φ(jd)=d=1ndφ(d)i=1n/dj=1m/dφ(id)φ(jd)pi,pjμ(p)=d=1ndφ(d)p=1n/dμ(p)i=1n/dpj=1m/dpφ(idp)φ(jdp)=t=1ndtdφ(d)μ(t/d)i=1n/tφ(it)j=1m/tφ(jt)t=dp

f(n)=dndφ(d)μ(n/d),预处理是简单的,可以做到 O(nlogn)

g(k,n)=i=1nφ(ik),由于 ikm,显然此式只有 O(nlogn) 种取值,也可以直接预处理。

那么原式就成了

t=1ndtdφ(d)μ(t/d)i=1n/tφ(it)j=1m/tφ(jt)=t=1nf(t)g(t,n/t)g(t,m/t)

发现这个式子不太好数论分块,考虑设 h(a,b,n)=i=1nf(i)g(i,a)g(i,b),那么原式即可数论分块,即

t=1nf(t)g(t,n/t)g(t,m/t)=n/l=n/r,m/l=m/rh(n/r,m/r,r)h(n/r,m/r,l1)

(可以看成是直接对 f(t)g(t,n/t)g(t,m/t) 求前缀和)

但是 h 的取值数量很多,预处理不论是时间还是空间开销都是极大的。

考虑根号分治,设一个阈值 B,对于 m/rB 的数预处理,对于 m/r>B 的数,我们有 r<m/B,这一段可以直接暴力。

这时我们考虑 h 的取值数量量级。对于 h(a,b,k),不妨设 ab,我们有 bkn,故取值数量为 Bi=1Bn/i=Bni=1B1/i=BnlogB

总时间复杂度为 O(nlogn+BnlogB+T(nB+n)),空间复杂度为 O(nlogn+BnlogB)。若要最小化上面那个式子,我们就需要满足 B2logB=T,近似解为 B=50

P5572 [CmdOI2019]简单的数论题

题意

i=1nj=1mφ(lcm(i,j)gcd(i,j))

23333 取模的值。

思路

以下设 nm

我们有

i=1nj=1mφ(lcm(i,j)gcd(i,j))=i=1nj=1mφ(ijgcd(i,j)2)=d=1ni=1nj=1mφ(ijd2)[gcd(i,j)=d]=d=1ni=1n/dj=1m/dφ(ij)[gcd(i,j)=1]

gcd(i,j)=1,我们有 φ(ij)=φ(i)φ(j)。于是有

d=1ni=1n/dj=1m/dφ(ij)[gcd(i,j)=1]=d=1ni=1n/dj=1m/dφ(i)φ(j)pi,pjμ(p)=d=1np=1n/dμ(p)i=1n/dpφ(ip)j=1m/dpφ(jp)=t=1nptμ(p)i=1n/tφ(ip)j=1m/tφ(jp)t=dp

g(k,n)=i=1nφ(ik),由于 ikm,显然此式只有 O(nlogn) 种取值,可以直接预处理。

那么有

t=1nptμ(p)i=1n/tφ(ip)j=1m/tφ(jp)=t=1nptμ(p)g(p,n/t)g(p,m/t)

再设 h(a,b,n)=i=1npiμ(p)g(p,a)g(p,b)

那么按 P4240 的套路做就行了。

注意预处理 h 的时候我们需要先预处理 piμ(p)g(p,a)g(p,b),预处理瓶颈就在这里,计算一下,有

O(i=1Bj=1Bp=1n/jn/jp)=O(ni=1Bj=1B1/jp=1n/j1/p)=O(ni=1Bln(B)ln(n))=O(nBln(B)ln(n))

总时间复杂度即为 O(nlogn+nBlogBlogn+T(n/Blog(n/B)+n)),最优的 B 满足 B2logB=T,近似解为 B=80

posted @   bykem  阅读(134)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示