数论学习笔记(整除分块+积性函数+筛子)

数论分块

看之前没有讲过先提一下,后面会用到。

问题一般是已知一个数 \(n\) 和两个函数 \(f,g\),求 \(\sum_{x=1}^n f(i)g(\left\lfloor\frac{n}{x}\right\rfloor)\)

这个东西可以考虑 \(\left\lfloor\frac{n}{x}\right\rfloor\) 有多少种不同的取值,假设 \(\left\lfloor\frac{n}{x}\right\rfloor=y\)

考虑根号分治,对于 \(x<\sqrt{n}\),取值显然最多 \(\sqrt{n}\) 种,对于 \(x>\sqrt{n}\)\(y\le \sqrt{n}\),最多也只有 \(\sqrt{n}\),所以总取值数是 \(2\sqrt{n}\) 级别的。

知道这个东西怎么求出对于一个取值 \(y\),满足这个取值的区间 \([l,r]\) 呢?

一开始学这个东西的时候我是直接整体二分的,这个应该大家都会。

考虑对于一个 \(l\),怎么去求 \(r\)

\(k=\left\lfloor\frac{n}{l}\right\rfloor\)\(k\le \frac{n}{l}\)

\[\left\lfloor\frac{n}{k}\right\rfloor \ge \left\lfloor\frac{n}{\frac{n}{l}}\right\rfloor=l \]

因为 \(k=\max l\),所以 \(r=\left\lfloor\frac{n}{\left\lfloor\frac{n}{l}\right\rfloor}\right\rfloor\)

for(int l=1,r;l<=n;l=r+1){
    r=n/(n/l);
    //work(l,r)
}

时间复杂度显然 \(O(\sqrt{n})\)


先来个例题。P2261

已知 \(n,k\),求

\[\sum_{i=1}^n k\bmod i \]

\(n,k\le 10^9\)

做法比较简单,就是考虑 \(k\bmod i=k-i\left\lfloor\frac{k}{i}\right\rfloor\),前面部分是 \(nk\),后面部分直接用板子即可。code(用整体二分写的)。

P2260 和这个题做法几乎一样。


P3935

\(x\) 分解质因数结果为 \(x=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\),令\(f(x)=(k_1+1)(k_2+1)\cdots (k_n+1)\),求 \(\sum_{i=l}^rf(i)\)\(998\,244\,353\) 取模的结果。

\(l,r\le 10^{14}\)

\(f(x)\) 显然就是 \(x\) 的因数个数,然后这个区间和可以变成前缀和的形式,也就是求 \(\sum_{i=1}^n f(i)\),直接考虑一个数作为因数对答案的贡献, \(i\) 对答案的贡献显然就是 \(\left\lfloor\frac{n}{i}\right\rfloor\),然后直接整除分块即可。

积性函数

就是一类函数的定义满足对于任意互质的数 \(a,b\)\(f(ab)=f(a)f(b)\)

对于任意数 \(a,b\) 都满足 \(f(ab)=f(a)f(b)\) 的函数称为完全积性函数。

容易发现 \(f(1)=1\)

所以也可以写成分段形式:

\[f(x)=\begin{cases}1&x=1\\f(x)&x=p^k,\text{p is prime}\\\prod_{}f(p_i^{k_i})& \text{otherwise}\end{cases} \]

也就是先处理出质数幂次的地方的取值,然后就是相乘的形式,这个可以直接用线性筛。

下面是几个常见的积性函数。

  • \(I\)\(f(x)=1\)
  • \(F_k\)\(f(x)=x^k\)
  • 欧拉函数
  • 莫比乌斯函数
  • \(d(x)\),表示 \(x\) 的约数个数,还有约数之和。

一个等式:

\[d(ij)=\sum_{x|i}\sum_{y|j}[\gcd(x,y)==1] \]

这个证明起来也比较简单,考虑对于每个质数,在 \(x,y\) 中选到的总方案为它的指数加一,这个等式在P3327中用到。

欧拉函数

\(\varphi(x)\) 表示 \([1,x]\) 有多少个数与 \(x\) 互质,这就是欧拉函数。


首先来证明这个是积性函数。

考虑对于两个数 \(a,b\),假设 \(S_a\) 为与 \(a\) 互质的数的集合,\(S_b\) 表示与 \(b\) 互质的数的集合。

那么任意取 \(x\in S_a,y\in S_b\),可以构造出 \(xb+ya\)\(ab\) 互质。

为什么呢?首先 \(\gcd(a,x)=1,\gcd(b,x)=1\to \gcd(ab,x)=1\)

那么 \(\gcd(xb+ya,a)=\gcd(xb,a)=1\),同理与 \(b\) 也互质。

再证明已经取完了所有的数,由于 \(a,b\) 互质,所以 \(xb+ya\)\(\bmod ab\) 意义下可以取遍所有数,那么如果 \(x\notin S_a\),那么就不互质了,同理 \(y\) 也是。

所以 \(\varphi(ab)=\varphi(a)\varphi(b)\)


然后来考虑咋求。

积性函数都是先考虑质数幂次处的取值。

\(f(p^k)=p^k-p^{k-1}=p^{k-1}(p-1)\)

那么 \(f(x)=\prod p_k^{k_i-1}(p_k-1)=x\prod\frac{p_i-1}{p_i}\)

暴力做就是 \(\sqrt{x}\) 的。

int euler_phi(int n) {// 贺的
  int ans = n;
  for (int i = 2; i * i <= m; i++)
    if (n % i == 0) {
      ans = ans / i * (i - 1);
      while (n % i == 0) n /= i;
    }
  if (n > 1) ans = ans / n * (n - 1);
  return ans;
}

然后考虑筛,也很简单,考虑如果当前是之前没有出现过的就直接乘上其欧拉函数值,否则之前出现过,容易发现 \(\varphi(p^k)=\varphi(p^{k-1})p\) 所以直接乘上即可,时间复杂度 \(O(n)\)

void work(){
	ou[1]=1;
	for(int i=2;i<=N;i++){
		if(!b[i])p[++cnt]=i,ou[i]=i-1;
		for(int j=1;j<=cnt&&p[j]*i<=N;j++){
			b[p[j]*i]=1;
			if(i%p[j]!=0)ou[i*p[j]]=ou[i]*(p[j]-1);
			if(i%p[j]==0){
				ou[i*p[j]]=ou[i]*p[j];
				break;
			}
		}
	}
}

下面来个等式。

\[\sum_{d|n} \varphi(d)=n \]

这个东西考虑证明,把 \(1\le x\le n\) 的数 \(x\) 拆成 \(\gcd(n,x)\times \frac{x}{\gcd(n,x)}\)\(\frac{x}{\gcd(x,n)}\) 显然与 \(\frac{n}{\gcd(x,n)}\) 互质,对于 \(d|n\),满足条件的个数就是 \(\varphi(\frac{n}{d})\),换成枚举 \(\frac{n}{d}\) 就可以得到上面的式子了。

来个例题

P2158

有一个 \(n\times n\) 的矩阵,有一个人站在 \((1,1)\),问他可以看到多少人。

\(n\le 40000\)

本质上就是这个东西

\[\sum_{i=1}^n \sum_{j=1}^n [\gcd(i,j)==1] \]

考虑取一半,变成

\[\sum_{i=1}^n \sum_{j=1}^i [\gcd(i,j)==1]=\sum_{i=1}^n \varphi(i) \]

算出来乘个 \(2\) 即可。

code

欧拉定理

对于 \(\gcd(a,p)=1\),满足

\[a^{\varphi(p)} \equiv 1 \pmod p \]

考虑 \(a^x\)\(\bmod p\) 意义下的取值,首先肯定是 \([0,p-1]\),假设就是 \([1,p]\) 好了。

然后这个取值一定是与 \(p\) 互质,如果不互质,也就是 \(\gcd(a^x,p)>1\),那么显然 \(\gcd(a,p)>1\) 矛盾。

然后可以发现,如果一个数 \(b\)\(p\) 互质,那么 \(ab\) 也和 \(p\) 互质。

所以开始构造一个序列 \(r_1,r_2,...,r_{\varphi(p)}\),表示所有与 \(p\) 互质的数。

考虑序列 \(ar_1,ar_2...ar_{\varphi(p)}\) ,这个序列在模 \(p\) 意义下必然两两不同,可以用反证法简单证明,然后又可以发现这个序列所有数与 \(p\) 互质。

所以

\[\prod r_i=\prod ar_i=a^{\varphi(p)}\prod r_i \]

所以可以证明 \(a^{\varphi(p)} \bmod p=1\)

如果 \(p\) 是质数,就可以证明费马小定理,\(a^{p-1}\bmod p=1\)


莫比乌斯函数、反演

先进行一个引入。

之前讲过二项式反演,反演的本质就是两个序列 \(f,g\) 满足一定关系,可以用 \(g\) 表示 \(f\),然后反演就是把 \(f\) 来表示 \(g\),二项式反演很有用是因为可以 \(O(n\log n)\) 的多项式卷积加速,否则很多反演都可以用 \(O(n^2)\) 直接做。

比如下面的反演是这样一个东西:

\[f_n=\sum_{n|d}g_d \]

考虑怎么去反演,暴力 \(O(n^2)\) 的自然不用说了。

此时就可以用莫比乌斯函数写成更加优美的形式了(虽然还是 \(O(n^2)\)

\[g_n=\sum_{n|d}\mu(\frac{d}{n})f_d \]

本质上这里莫比乌斯函数就是当一个容斥系数。

给出 \(\mu\) 的定义:

\[\mu(x)=\begin{cases}1&x=1\\-1&x=p,\text{p is prime}\\0&x=p^k,\text{p is prome},k\ge 2\\ \prod_{}f(p_i^{k_i})& \text{otherwise}\end{cases} \]

再去考虑上面那个容斥,可以发现贡献算的就是多出来的质因数,进行一个多维容斥。

莫比乌斯函数也可以直接用线性筛算。


考虑 \(\mu\)\(\varphi\) 之间的关系。

首先可以得到 \(n=\sum_{d|n}\varphi (d)\),这个把所有 \(\le n\) 的数按照 \(\gcd(i,n)\) 分组即可。

直接反演:

\[n=\sum_{d|n}\varphi (d)\\ \varphi(n)=\sum_{d|n}\mu(d)\frac{n}{d}\\ \varphi =\mu * id \]


\[g(n)=\prod_{d|n}(\frac{n}{d})^{\mu(d)} \]

两边同取 \(\ln\)

\[\ln g(n)= \sum_{d|n} \mu(d) \ln (\frac{n}{d}) \]

反演回来。

\[\ln n=\sum_{d|n} \ln g(d)\\ n=\prod_{d|n} g(d) \]

大力分类讨论,可以得到:

\[\mu(x)=\begin{cases}1&x=1\\p&x=p,\text{p is prime}\\p&x=p^k,\text{p is prome},k\ge 2\\ 1& \text{otherwise}\end{cases} \]

这不是积性函数,但是可以线性做。


来个用这个反演的题

bzoj2986bzoj2440P4318

定义一个数 \(x\) 是好的,当且仅当 \(x\) 不含有一个平方因子,求第 \(n\) 个好的数。

\(n\le 10^{10}\)

第一步显然直接二分即可,然后相当于求前缀好的数的个数,这个平方因子定义显然就可以变成 \(\mu^2(x)\),等于一就表示是好的数,然后相当于求 \(\sum_{i=1}^n \mu^2(i)\),可以直接上杜教筛或者 min-25 筛,但是常数巨大而且没必要。

考虑设 \(f_i\) 表示是 \(i^2\) 倍数的数的个数,\(g_i\) 表示 \(i^2\)\(x\) 的最大平方因子的 \(x\) 的个数,那么要求的就是 \(g_1\)

那么显然

\[f_n=\sum_{n|d}g_d\\ g_n=\sum_{n|d}\mu(\frac{d}{n})f_d\\ f_i=\left\lfloor\frac{n}{i^2}\right\rfloor \]

那么 \(d\) 只需要枚举到 \(\sqrt{n}\) 即可,因此总复杂度 \(O(\sqrt{n}\log n)\)

code


有许多数论题目与 \(\gcd\) 的求和有关,可以用莫比乌斯反演做,当然不是上面 \(O(n^2)\) 的形式。

首先需要证明,\(\sum_{d|n}\mu(d)=[n==1]\)

\(n=1\) 显然,否则考虑每个质数的贡献,就相当于是一个二进制数 \(2^n-1\),每一位选或者不选,总贡献就是 \(0\)

莫反的基本形式就是

\[[\gcd(a,b)==1]=\sum_{d|\gcd(a,b)}\mu (d) \]

然后可以把 \(d\) 的枚举放到 \(a,b\) 前面,这样就需要满足 \(d|a,d|b\),这样就可以反演了。

然后来几个例子,默认 \(n<m\)

已知 \(n,m\),求

\[\sum_{i=1}^n \sum_{j=1}^m [\gcd(i,j)==1] \]

\[=\sum_{i=1}^n \sum_{j=1}^m \sum_{d|\gcd(i,j)}\mu(d)\\ =\sum_{d=1}^n \mu (d)\left\lfloor\frac{n}{d}\right\rfloor \left\lfloor\frac{m}{d}\right\rfloor \]

然后整除分块、暴力即可。

已知 \(n,m\),求

\[\sum_{i=1}^n \sum_{j=1}^m \gcd(i,j) \]

\[=\sum_{i=1}^n \sum_{j=1}^m \sum_{d|\gcd(i,j)} \varphi (d)\\ =\sum_{d=1}^n \varphi (d)\left\lfloor\frac{n}{d}\right\rfloor \left\lfloor\frac{m}{d}\right\rfloor \]

已知 \(n,m\),求

\[\sum_{i=1}^n \sum_{j=1}^m f(\gcd(i,j)) \]

\(f(x)\) 是一个函数。

此时枚举 \(\gcd(i,j)\) 即可。

\[=\sum_{p=1}^n f(p) \sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor} \sum_{j=1}^{\left\lfloor\frac{m}{p}\right\rfloor} [\gcd(i,j)==1]\\ =\sum_{p=1}^n f(p)\sum_{d=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\mu(d) \left\lfloor\frac{n}{dp}\right\rfloor \left\lfloor\frac{m}{dp}\right\rfloor \]

此时令 \(T=dp\)

\[\sum_{T=1}^n (\sum_{d|T}\mu(d)f(\frac{T}{d}))(\left\lfloor\frac{n}{T}\right\rfloor\left\lfloor\frac{m}{T}\right\rfloor) \]

\(\sum_{d|T}\mu(d)f(\frac{T}{d})\) 部分可以直接狄利克雷卷积预处理,然后就可以整除分块了。

莫反题很多,但方法都差不多,试试看!

P5518

阴间题。

\(type=1\)

\[\prod_{i=1}^A \prod_{j=1}^B \prod_{k=1}^C \frac{\text{lcm}(i,j)}{\gcd(i,k)}\\ =(\prod_{i=1}^A \prod_{j=1}^B \frac{ij}{\gcd(i,j)})^C (\prod_{i=1}^A\prod_{k=1}^C \frac{1}{\gcd(i,k)})^B\\ \]

这个时候把问题分成两半。

\[\prod_{i=1}^A \prod_{k=1}^C \frac{1}{\gcd(i,k)}\\ =\prod_{i=1}^A \prod_{d|i} (\frac{1}{d})^{\sum_{k=1}^C [\gcd(i,k)=d]}\\ =\prod_{i=1}^A \prod_{d|i} (\frac{1}{d})^{\sum_{p|\frac{i}{d}}\mu(p)\frac{C}{dp}}\\ =\prod_{i=1}^A \prod_{T|i} (\prod_{d|T}(\frac{1}{d})^{\mu(\frac{T}{d})})^{\frac{C}{T}}\\ = \prod_{i=1}^A \prod_{T|i} F(T)^{\frac{C}{T}}\\ = \prod_{T=1}^A F(T)^{\frac{AC}{T^2}} \]

另一半就是在这个的基础上乘一个 \(\prod_{i=1}^A \prod_{j=1}^B ij\)

20pts

\(type=1\)

\(g(x)=\frac{x(x+1)}{2}\)

\[\prod_{i=1}^A \prod_{j=1}^B \prod_{k=1}^C \frac{\text{lcm}(i,j)}{\gcd(i,k)}^{ijk}\\ =(\prod_{i=1}^A \prod_{j=1}^B (\frac{ij}{\gcd(i,j)})^{ij})^{g(C)} (\prod_{i=1}^A\prod_{k=1}^C (\frac{1}{\gcd(i,k)})^{ik})^{g(B)}\\ \prod_{i=1}^A \prod_{j=1}^B (\frac{1}{\gcd(i,j)})^{ij}\\ = \prod_{i=1}^A (\prod_{d|i} (\frac{1}{d})^{\sum_{p|\frac{i}{d}}\mu(p)g(\frac{B}{dp})dp})^i\\ = \prod_{i=1}^A (\prod_{T|i} G(T)^{g(\frac{B}{T})})^i\\ = \prod_{T=1}^A G(T)^{g(\frac{B}{T})g(\frac{A}{T})T}\\ \]

其实和 \(type=0\) 比较类似。

60pts

\(type=2\)

\[\prod_{i=1}^A \prod_{j=1}^B \prod_{k=1}^C \frac{\text{lcm}(i,j)}{\gcd(i,k)}^{\gcd(i,j,k)}\\ = \prod_{i=1}^A \prod_{j=1}^B \prod_{k=1}^C \prod_{d=1}^A \frac{\text{lcm}(i,j)}{\gcd(i,k)}^{d[\gcd(i,j,k)=d]}\\ =\prod_{d=1}^A (\prod_{i=1}^{\frac{A}{d}} \prod_{j=1}^{\frac{B}{d}} \prod_{k=1}^{\frac{C}{d}} \frac{\text{lcm}(i,j)d}{\gcd(i,k)d}^{[\gcd(i,j,k)=1]})^d\\ =\prod_{d=1}^A (\prod_{i=1}^{\frac{A}{d}} \prod_{j=1}^{\frac{B}{d}} \prod_{k=1}^{\frac{C}{d}} \frac{\text{lcm}(i,j)}{\gcd(i,k)}^{\sum_{p|\gcd(i,j,k)}\mu(p)})^d\\ =\prod_{d=1}^A (\prod_{p=1}^{\frac{A}{d}} (\prod_{i=1}^{\frac{A}{dp}} \prod_{j=1}^{\frac{B}{dp}} \prod_{k=1}^{\frac{C}{dp}} \frac{\text{lcm}(i,j)}{\gcd(i,k)})^{\mu(p)})^d\\ =\prod_{T=1}^{A} Q(\frac{A}{T},\frac{B}{T},\frac{C}{T})^{H(T)} \]

这里的 \(Q\) 就是 \(type=0\) 的情况。

大力做,是 \(O(Tn\log^2 n)\) 的,寄了,可以对每一个都整除分块一下。

复杂度不知道,反正是最优解第三。

code

按素数考虑

别莫反魔怔了。

\([1,n]\) 中选出若干个数,使得全部 \(\gcd=1\),求方案数。

直接枚举 \(\gcd\) 即可。

\[\sum_{d=1}^n \mu(d) 2^{\frac{n}{d}} \]

直接做 \(O(n)\),可以整除分块,复杂度 \(O(\sqrt{n}\log n)\)

那如果要求 \(\gcd=1,\text{lcm}=L\) 呢?loj2257

这个就相对阴间了。

莫反:

容斥一下,分别算 \(\gcd>1,\text{lcm}<L,\gcd>1 并且 \text{lcm}<L\) 的方案数即可。

前两个可以直接 \(O(n\log n)\) 做,最后那个可以枚举 \(\text{lcm}\) 然后做,复杂度 \(O(n\log^2 n)\),很寻,而且不能修改。

考虑把 \(f(i)=\frac{L}{i}\),那么 \(\text{lcm}=L\) 等价于 \(f(i)\)\(\gcd=1\)

因此把每个数看成二元组 \((i,\frac{L}{i})\),相当于选出若干个使得两个都 \(\gcd =1\)

\[\sum_{d_1|L} \sum_{d_2d_1|L} \mu(d_1)\mu(d_2) (?) \]

大概是这样。

还是很难算,但是会发现含有平方因子的东西 \(\mu=0\) 没有贡献,因此只需要考虑若干个质数乘起来即可。

每个质数只有选或者不选,因此可以状压,就变成了选若干个数与起来等于 \(0\)

直接 FWT,复杂度 \(O(2^{2w(L)})\)\(w(L)\) 表示 \(L\) 质因子个数。

带修的话就考虑修改的每个点对 \(0\) 点的贡献是 \(1\) 或者 \(-1\),直接算上即可,这样复杂度 \(O(w(L)2^{2w(L)})\)

丢番图

这个东西洛谷评绿,但是总是推不出来。

\[\frac{1}{a}+\frac{1}{b}=\frac{1}{c}\\ bc+ac=ab\\ ab-bc-ac+c^2=c^2\\ (a-c)(b-c)=c^2 \]

loj6482 \(\color{Gold}\bigstar\)

\(x=a-c,y=b-c\),那么 \(\gcd(a,b,c)=\gcd(x,y,c)=1\)

因为 \(x,y\) 中的每个质因子 \(c\) 中都有,所以只需要满足 \(\gcd(x,y)=1\),那么可以发现 \(x,y\) 都需要是完全平方数。

写个暴力式子,直接去枚举 \(c,\sqrt{x}\)

\[\sum_{c=1}^n \sum_{i|c} [\gcd(i,\frac{c}{i})=1 且 i^2+c\le n 且 \frac{c^2}{i^2}+c\le n] \]

后面两个条件比较阴间,换到前面来。

\[\sum_{c=1}^n \sum_{i=\sqrt{\frac{c^2}{n-c}}}^{\sqrt{n-c}} [\gcd(i,c)=i且\gcd(i,\frac{c}{i})=1]\\ =\sum_{i=1}^{\sqrt{n}}\sum_{c=1}^{R_i} [\gcd(i,c)=i且\gcd(i,\frac{c}{i})=1]\\ =\sum_{i=1}^{\sqrt{n}}\sum_{c=1}^{R_i/i} [\gcd(i,c)=1]\\ =\sum_{d=1}^{\sqrt{n}}\mu(d)\sum_{i=1}^{\sqrt{n}/d}\frac{R_i}{id} \]

code

杜教筛

这个算法用来算积性函数前缀和。也就是

\[S(n)=\sum_{i=1}^n f(i) \]

单次询问复杂度为 \(O(n^{\frac{2}{3}})\)

考虑构造一个函数 \(g\),满足 \(g\) 的前缀和很好求,并且 \(f\)\(g\) 的狄利克雷卷积出的函数 \(h\) 的很好求。

\[\sum_{i=1}^n h(i)=\sum_{i=1}^n \sum_{d|i}f(d)g(\frac{i}{d}) =\sum_{d=1}^n g(d)\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}f(i)=\sum_{d=1}^n g(d) S(\left\lfloor\frac{n}{d}\right\rfloor)\\ =g(1)S(n)+\sum_{d=2}^n g(d)S(\left\lfloor\frac{n}{d}\right\rfloor) \]

因此可以得到

\[S(n)=\frac{\sum_{i=1}^n h(i)-\sum_{d=2}^n g(d)S(\left\lfloor\frac{n}{d}\right\rfloor)}{g(1)} \]

\(\sum_{i=1}^n h(i)\) 很好求,右边的东西可以直接整除分块,然后一直递归下去,记忆化一下复杂度是 \(O(n^{\frac{3}{4}})\)

用线性筛筛出前 \(n^{\frac{2}{3}}\) 的答案,复杂度就是 \(O(n^{\frac{2}{3}})\)

主要的难度在于构造 \(g\),所以杜教筛的使用范围还是比较小的。


P4213

已知 \(n\),求下面两个式子的值

\[\sum_{i=1}^n \mu(i)\\ \sum_{i=1}^n \varphi(i) \]

\(n\le 2^{31}\)

这两个构造比较简单,都是 \(I,f(x)=1\) 即可。这个东西前缀和很好求,而且卷积后的东西:

\[\mu * I(n)=\sum_{d|n}\mu(d)=[n==1]\\ \varphi * I(n)=\sum_{d|n} \varphi(d)=n \]

前缀和都很简单,那么直接求即可。

放一个求 \(\varphi\) 的代码:

ll sum_phi(int n){
	if(n<=1e6)return phi[n];
	if(mp_phi.count(n))return mp_phi[n];
	ll ans=1ll*n*(1ll*n+1)/2,r;
	for(ll l=2;l<=n;l=r+1){
		r=n/(n/l);
		ans-=1ll*(r-l+1)*sum_phi(n/l);
	}
	return mp_phi[n]=ans;
}

P3768

给定两个整数 \(n,p\),求

\[\sum_{i=1}^n \sum_{j=1}^n ij\gcd(i,j) \pmod p \]

\(n\le 10^{10}\)

先和仪仗队差不多,直接推式子。

\[=\sum_{i=1}^n \sum_{j=1}^n ij\sum_{d|\gcd(i,j)}\varphi(d)=\sum_{d=1}^n \varphi(d) \sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor} \sum_{j=1}^{\left\lfloor\frac{n}{d}\right\rfloor} ijd^2\\ = \sum_{d=1}^n \varphi(d)d^2 (\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor} i)^2 \]

后面那个部分可以直接整除分块然后 \(O(1)\) 算,问题变成求 \(\sum_{d=1}^n \varphi(d)d^2\)

这个东西配一个 \(g(x)=x^2\),可以发现 \((f * g)(n)=n^3\),所以可以直接杜教筛求了。

这个整除分块+杜教筛的复杂度应该是 \(O(n^{\frac{2}{3}})\) 的。

代码可以看 froggy 的题解,我写的代码疯狂 WA,调不出来。

min 25 筛

这个东西比杜教筛跟牛一点,可以处理几乎所有积性函数了。

依然考虑

\[S(n)=\sum_{i=1}^n f(i) \]

这里需要满足 \(f(x)\) 是积性函数并且在 \(p\) 为质数时 \(f(p)\) 时一个关于 \(p\) 的多项式,并且 \(f(p^c)\) 比较好求。

主要的思想是把这个和拆成 \(1\),质数,合数这三个部分。

part 1 预处理

下面约定 \(p_i\) 表示第 \(i\) 个质数。

令一个完全积性函数 \(f'(x)\) 在质数位置取值与 \(f(x)\) 相同,如果这个比较难构造,可以变成多个函数相加的形式。

先考虑这样一个 dp,\(g(n,k)\) 表示对于所有 \(2\le i\le n\),满足 \(i\) 是质数或者 \(i\) 的最小质因数 \(\ge p_k\)\(f'(i)\) 的和。

考虑这个东西去转移。

如果 \(p_k^2>n\),那么 \(p_k\) 去不掉任何一个合数,因此没有贡献,所以 \(g(n,k)=g(n,k-1)\)

否则,考虑 \(p_k\) 会把那些给删掉,容易发现就是满足最小质因数为 \(p_k\) 的合数。

由于是完全积性函数,所以可以把一个 \(f'(p_k)\) 拿出来,这样就得到了 \(f'(p_k)g(\left\lfloor\frac{n}{p_k}\right\rfloor,k-1)\)

然后考虑有一些东西会被多算,也就是含有小于 \(p_k\) 的质数,减掉即可,整理一下就是

\[g(n,k)=g(n,k-1)-f'(p_k)(g(\left\lfloor\frac{n}{p_k}\right\rfloor,k-1)-g(p_k-1,k-1)) \]

此处由于 \(g(n,k)\) 是不算 \(1\) 的,所以 \(f'(p_k)\) 恰好被保留了下来。

注意这个地方是拿完全积性函数 \(f'(x)\) 算的,网上一些博客拿 \(f(x)\) 算显然是错的。


part 2 算答案

考虑类似的,设 \(G(n,k)\) 表示对于所有 \(2\le i\le n\),满足 \(i\) 的最小质因数 \(\ge p_k\)\(f(i)\) 的和。

考虑这个东西怎么算,把它拆成质数,合数两个个部分。

质数部分的话,\(f(p)=f'(p)\),所以可以用 \(g\) 来算,也就是 \(g(n,|P|)\)\(|P|\)\(\le n\) 质数总个数,然后由于前 \(k\) 个质数是没有贡献的,所以再减去 \(g(p_k,k)\)

合数部分,考虑枚举质数以及枚举其次数即可,这部分贡献是 \(\sum_{j>k} \sum_{e\ge 1} f(p_j^e)(G(\left\lfloor\frac{n}{p_j^e}\right\rfloor,j)+[p>1])\)

后面要加 \(p>1\) 是因为 \(G\) 不算 \(1\) 的贡献,要加上 \(f(p_j^e)\) 的贡献,去掉 \(e=1\) 是因为前面质数部分已经算过了。

所以可以得到

\[G(n,k)=g(n,|P|)-g(p_k,k)+\sum_{j>k} \sum_{e\ge 1} f(p_j^e)(G(\left\lfloor\frac{n}{p_j^e}\right\rfloor,j)+[p>1]) \]

最后的答案就是 \(f(1)+G(n,0)\)

part 3 具体实现

先去求 \(g(n,|P|)\),可以发现第一维都是 \(\left\lfloor\frac{n}{p_k}\right\rfloor\) 的形式,所以第一维出现的数只有 \(\sqrt{n}\) 个,那么先预处理出所有 \(g(x,0)\),然后一层一层地进行递推即可。

注意计算初值时,一定要先把 \(f'(1)\) 给去掉。

然后直接照着上面的式子去算 \(G\) 即可,复杂度为 \(O(\frac{n^{\frac{3}{4}}}{\log n})\),不过也有人说是 \(O(n^{1-ϵ})\)


loj 6235

\([1,n]\) 素数个数。

\(n\le 10^{11}\)

显然就相当于是 \(f'(x)=1\),然后直接求 \(g(n,|P|)\) 即可。

这个东西直接用上面的东西 dp 一遍即可。

贴个核心代码:

int get_id(int x){
    if(x<sq)return mp1[x];
    return mp2[n/x];
}
signed main(){
    scanf("%lld",&n);sq=sqrt(n);
    pre(sq);
    for(int l=1,r;l<=n;l=r+1){
        r=n/(n/l);
        w[++m]=n/l,g[m]=w[m]-1;
        if(n/l<sq)mp1[n/l]=m;else mp2[r]=m;// 注意这里 mp2 是 r,调了很久,是因为存的值是 n/l,后面调用是 n/x,也就是 n/(n/l),所以直接就是 r
    }
    for(int i=1;i<=cnt;i++)
        for(int j=1;j<=m&&p[i]*p[i]<=w[j];j++)
            g[j]-=g[get_id(w[j]/p[i])]-s[p[i]-1];//这里 s[i] 表示 [1,i] 的素数个数
    printf("%lld",g[1]);
}

P5325

已知积性函数 \(f(x)\) ,满足 \(f(p^k)=p^k(p^k-1)\)

\[\sum_{i=1}^n f(i) \]

\(n\le 10^{10}\),答案对 \(10^9+7\) 取模。

先考虑求质数地方的,那么就是 \(f(p)=p(p-1)\),拆成完全积性函数,就是 \(f(p)=(p^2)-p\),对两个分别处理然后相减即可,然后再去求一下答案。

求答案部分代码:

int G(int n,int k){
    if(p[k]>n)return 0;
    int ans=(g[get_id(n)]+s1[p[k]]-s2[p[k]]+mod)%mod;
    for(int i=k+1;i<=cnt&&p[i]*p[i]<=n;i++)
        for(int t=p[i];t<=n;t*=p[i]){
            int T=t%mod;
            ans=(ans+T*(T-1)%mod*(G(n/t,i)+(t!=p[i]))%mod)%mod;
        }
    return ans;
}

code


posted @ 2022-08-10 21:24  houzhiyuan  阅读(168)  评论(0编辑  收藏  举报