Loading

数论知识点

网络赛数论板子题自闭

特此开坑

ACM数论知识点

参考博客

积性函数的性质及证明

杜教筛

莫比乌斯反演

反演入门题单

快速幂

ll qpow(int a,int p){
	ll ans = 1;
	while(p){
		if(p & 1)ans = (ans * a) % mod;
		a = (a * a) % mod;
		p >>= 1;
	}
    return ans;
}

gcd

int gcd(int a,int b){
	return a % b == 0 ? b : gcd(b, a % b);
}

整除分块

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

1. 积性函数

如果已知一个函数为数论函数,且\(f(1)=1\),并且满足以下条件,若对于任意的两个互质的正整数\(p,q\)都满足\(f(p⋅q)=f(p)⋅f(q)\),那么则称这个函数为积性函数

常见的积性函数

\(1. \mu(n)\)

莫比乌斯函数

  • $\mu(1) = 1 $

  • \(d=\Pi_{i=1}^{k}p_i\), 且 \(p_i\) 为互异素数时,\(\mu(d) = (-1)^k\)

  • \(d\) 含有任何质因子的幂次大于等于 \(2\) ,则 \(\mu(d) = 0\)

\(\mu * I = \epsilon\)

$2. \varphi(n) $

欧拉函数

表示 \([1,n)\) 内与 \(n\) 互质的数的个数

\(\varphi * I = id\)

\(\rightarrow \varphi * I * \mu = id * \mu\)

\(\rightarrow \varphi = id * \mu=\sum_{d|n}\mu(d)\cdot \dfrac n d\)

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

\(3. d(n)\)

约数个数

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

证明:

image-20200922094109729

\[d(n) =\prod_{i=1}^n(1+a_i),\ n = \prod_{i=1}^np_i^{a_i} \]

\(4. \sigma(n)\)

约数和函数

完全积性函数

\(1. \epsilon(n)\)

元函数, \(\epsilon(n) = [n==1]\)

\(f * \epsilon = f\)

\(2. I(n)\)

恒等函数, \(I(n) = 1\)

\(I * f = \sum_{d|n}f(d)\)

\(3. id(n)\)

单位函数, \(id(n) = n\)

\(lcy\)\(ppt\)

2. 欧拉函数

\[\varphi(n) = \begin{cases} 1 ,\ \ \ \ \ \ \ \ \ \ \ \ \text{n = 1} \\ numbers(gcd(n,i) == 1 \ for\ i\ \ in\ \ [1,n]) \end{cases}\]

欧拉函数\(\varphi(n)\)等于小于等于n的所有正整数中和n互素的数的个数

一些性质

性质一:

对于素数\(p\)

\[\varphi(p) = p - 1 \]

很显然,除了\(p\) 1到\(p-1\)和都\(p\)互素

性质二:

对于素数\(p\)

\[\varphi(p^k) = p^k - p^{k-1}=p^k(1-\frac1p) \]

证明:
对于[1,\(p^k\)]中的数n,若与\(p^k\)不互素,则必有

\[n = xp \]

\(x\in[1,2,...,p^{k-1}]\)
所以\(\varphi(p^k) = p^k - p^{k-1}\)得证,第一个式子是总数,第二是不互素的数的个数

性质三:(积性)

对于素数\(p\),\(q\)

\[\varphi(p*q) = \varphi(p) \varphi(q) \]

性质四: (计算公式)

对于任意正整数\(n\) 其中 \(n = \prod_{i=1}^{i = k}p_i^{e_i}\)

\[\varphi(n) = n\prod_{i=1}^{i = k}(1-\frac1{p_i}) \]

所以在欧拉筛中

if (i % prime[j] == 0) {//因数都一样,多乘了一个p
	phi[i * prime[j]] = phi[i] * prime[j];
	break;
}
else {//积性
	phi[i * phi[j]] = phi[i] * (phi[j] - 1);
}

证明:

\[\varphi(n) = \varphi(\prod_{i=1}^{i = k}p_i^{e_i}) \]

\[= \prod_{i=1}^{i = k}\varphi(p_i^{e_i}) \]

\[= \prod_{i=1}^{i = k}(p_i^{e_i}(1-\frac1{p_i})) \]

\[= n\prod_{i=1}^{i = k}(1-\frac1{p_i}) \]

证毕

性质五:

\(i \ mod \ p = 0\)

\[\varphi(i*p)=p*\varphi(i) \]

\(i \ mod \ p \neq 0\)

\[\varphi(i*p)=(p-1)*\varphi(i) \]

这条性质显然,由积性直接得出(\(i\),\(p\)互质)

对于第一条性质,首先要知道一个引理

\[if \ gcd(n,i) = 1 \ then \ gcd(n + i,i) = 1 \]

证明
\(n+i\)\(i\)有公因数\(k\),则\(n\)\(i\)也有公因数\(k\)矛盾
由此
\(gcd(a,b)=1\),则\(gcd(a,b+ka)=1\)\(k\in Z\)(\(k\)可以是负数)

因为\(i \ mod \ p = 0\),所以对于\(k\in[1,i]\)\(gcd(k,i)=1\)\(gcd(k,i*p)\)是等价的
\(gcd(k+xi,i)=1\)\(x\in[0,1,2,..,p-1]\)
对于\(k>i\)\(k\)来说,一定是由\(k\in[1,i]\)转移而来

所以 \(\varphi(i*p)=p*\varphi(i)\)

欧拉定理:

\(gcd(a,n) == 1\) ,则

\[a^{\varphi(n)} \ mod\ n \ = 1 \]

广义欧拉定理

\[a^b(mod\ n) = \begin{cases}a^{b\ \% \ \varphi(n)} &(mod\ n),&&a和n互质\\a^b \ & \ (mod \ n),&&b<\varphi(n)\\a^{b\ \% \ \varphi(n)+\varphi(n)}&(mod\ n),&&b\ge\varphi(n)\end{cases} \]

一般用作降幂,也可以用来求逆元

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

3. 莫比乌斯函数

先介绍莫比乌斯函数 \(\mu\) ,是一个常用的积性函数

\[\mu(x)= \begin{cases}1,& \text{x = 1}\\0,& \text{x的任何因子幂次数大于二}\\(-1)^{k}, & x = \prod_{i=1}^kp_i,p_i为互异的素数\end{cases} \]

一、性质

①、常用**

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

其中\([n=1]\)表示n == 1时候成立,为1,否则为0

也就是说任何大于1的整数n,其所有因子的莫比乌斯函数之和为0

②、

对于任意正整数n,

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

这个性质把莫比乌斯函数和欧拉函数联系在了一起

莫比乌斯反演

定理:
\(F(n)\)\(f(n)\) 是定义在非负整数集合的两个函数,且满足

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

则有

\[f(n) = \sum_{d|n}\mu(d)F(\frac{n}{d})=\sum_{d|n}\mu(\frac{n}{d})F(d) \]

利用卷积的性质不难整明

以及

\[\sum_{d|n}\mu(d) = \sum_{i=0}^k(-1)^iC_k^i \]

\[n = \prod_{i=1}^kp_i^{a_i} \]


4. 埃氏筛

bool isprime[maxn];
int prime[maxn],cnt;
void get(int N){
	for(int i = 0;i <= N;i++)isprime[i] = true;
	isprime[0] = isprime[1] = false;
	
	for(int i = 2;i <= n;i++){
		if(isprime[i]){
			prime[++cnt] = i;
			for(int j = i * i;j <= n;j += i){
				isprime[j] = false;
			}
		}
	}
} 

5. 线性筛

基本思想:

对于每一个数n,筛去所有小于等于n最小质因数的质数和n乘积的数

我感觉线性筛其实是筛积性函数的通用的方法

直接给出代码
线性筛中最精华的部分就是这一句话

if(i % prime[j] == 0)break;

它确保了每个数只被它的最小质因数访问

例如 i = 2*3*5, 则需要筛去 2*i ,不能筛去 3*i

观察 \(n=30\)\(n\) 的因数有 \(2,3,5\) ,则只会被 \(15 * 2\) 筛去一次

而不能被 \(10 * 3\) 筛去。

$ n = p_1{k_1}p_2...p_n^{k_n}$

\(n\) 只会被 \(p_1^{k_1-1}p_2^{k_2}...p_n^{k_n}\) 筛去

void get_mu(int n){
	mu[1] = 1;
	for(int i = 2;i <= n;i++){
		if(!vis[i]){
			prime[++cnt] = i;
            min_fac[i] = i;
		}
		for(int j = 1;j <= cnt && prime[j]*i <= n;j++){
			vis[prime[j]*i] = 1;
			if(i % prime[j] == 0)break;
            min_fac[prime[j]*i] = prime[j];
		}
	}
}

线性筛还可以用来分解质因数

因为可以记录每个数的最小质因数。

void fac(int n){
	while(n > 1){
		p[min_fac[n]]++;
		n /= min_fac[n];
	}
}

6. 迪利克雷卷积

两个函数 \(f\) , \(g\) 的迪利克雷卷积

\[f * g = \sum_{d|n}f(d)g(\dfrac n d) \]

满足交换律,结合律,分配律,可以当作乘法

7. 莫比乌斯反演

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

\[f(n) = \sum_{d|n}\mu(d)F(\frac nd) \]

另一种形式:

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

可以推出

\[ f(n) = \sum_{n|d}\mu(\dfrac dn)F(d) \]

8. 杜教筛

要求的东西 : \(\sum f(i)\)

\[h = f * g \]

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

\[\sum_{i=1}^{n}h(i)=\sum_{i=1}^{n}\sum_{d|i}g(d)\cdot f(\frac{i}{d})\\\to =\sum_{d=1}^{n}g(d)\cdot\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}f({i}) \]

\[\to \sum_{i=1}^{n}h(i)=\sum_{d=1}^{n}g(d)\cdot S(\lfloor\frac{n}{d}\rfloor) \]

​ 这一步的两个 \(\sum\) 的位置变换可以自己在纸上举了例子体会一下

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

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

9. min25筛

min25模板

一种低于线性复杂度的求积性函数前缀和的筛法。

适用条件:

  • \(f(p)\) 是多项式
  • \(f(p^k)\) 便于计算

思想:

\[\sum_{i=1}^nf(i) = \sum_{i \in Prime}f(i) + \sum_{i \notin Prime}f(i) \]

分为两个部分,第一部分是所有素数,第二部分是所有的合数

第一部分

搞来一个这样的函数 \(g(n,j)\)

\[g(n,j) = \sum_{i=1}^n[i \in Prime\ or\ minp(i) > P_j] i^k \]

所有的素数加上满足\(minp(i) > P_j\) 的所有 \(i\)

\([1-n]\) 中所有质数的 \(k\) 次方之和就是 \(g(n,x)\)\(P_x\) 是最后一个小于等于

\(\sqrt n\) 的质数

考虑 \(g(n,j)\) 的转移

\[g(n,j) = g(n,j-1) - P_j^k\bigg(g(\dfrac n {P_j},j-1)\ -g(P_j-1,j-1)\bigg) \]

这个东西自己在纸上写一些体会一下,注意 \(P_j\) 筛去的第一个数是 \(P_j^2\) , 第二个数不是 \(P_j^2+ P_j\)

第二部分

\[S(n,x) = \sum_{i=1}^n[minp(i) > P_x]f(i) \]

可以把 \(S(n,x)\) 也分成两部分,一部分是所有大于 \(P_x\) 的质数,另一部分是最小质因数大于 \(P_x\) 的合数,枚举最小质因子

\[S(n,x) = g(n) - sp_x + \sum_{p_k^e \le n \&k>n}f(p_k^e)\bigg(S \bigg(\dfrac n {p_k^e}\bigg) + [e \ne 1]\bigg) \]

\(e = 1\) 的时候, \(P_k\) 在前面枚举过了,不等于 \(1\) 时,需要加上 \(P_k^e\)

存下所有可能的 \(\lfloor\dfrac n x \rfloor\) , 做一个映射

\[idx(x)= \begin{cases}ind1[x] , \ \ x\le \sqrt n \\ind2[n/x],\ \ x>\sqrt n\end{cases} \]

要注意取模的时候不要爆数据范围

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9 + 7, inv6 = 166666668, inv2 = 500000004;
const int maxn = 1e6 + 10;
ll n, sqr;

ll prime[maxn], cnt, vis[maxn];
ll sp1[maxn], sp2[maxn];//sp1 p的前缀和,sp2 p^2的前缀和
ll w[maxn], tot;
ll g1[maxn], g2[maxn], ind1[maxn], ind2[maxn];

void get(int maxn) {
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) {
			prime[++cnt] = i;
			sp1[cnt] = (sp1[cnt - 1] + i) % mod;
			sp2[cnt] = (sp2[cnt - 1] + 1ll * i * i) % mod;
		}
		for (int j = 1; j <= cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0)break;
		}
	}
}
ll S(ll x, int y){
	if (prime[y] >= x)return 0;
	ll k = x <= sqr ? ind1[x] : ind2[n / x];
	ll ans = (g2[k] - g1[k] + mod - (sp2[y] - sp1[y]) + mod) % mod;
	for (int i = y + 1; i <= cnt && prime[i] * prime[i] <= x; i++)
	{
		ll pe = prime[i];
		for (int e = 1; pe <= x; e++, pe = pe * prime[i])
		{
			ll xx = pe % mod;
			ans = (ans + xx * (xx - 1) % mod * (S(x / pe, i) + (e != 1))) % mod;
		}
	}
	return ans % mod;
}

int main() {
	scanf("%lld", &n);
	sqr = sqrt(n);
	get(sqr);
	for (ll l = 1, r; l <= n; l = r + 1) {
		r = n / (n / l);
		w[++tot] = n / l;
		ll k = w[tot] % mod;
		g1[tot] = (k * (k + 1) % mod * inv2 - 1 + mod) % mod;
		g2[tot] = (k * (k + 1) % mod * (2 * k + 1) %mod * inv6 % mod + mod - 1) % mod;


		if (w[tot] <= sqr)ind1[n / l] = tot;
		else ind2[n / (n / l)] = tot;
	}
	for (int i = 1; i <= cnt; i++) {
		//g(n,j) 滚第一维
		for (int j = 1; j <= tot && prime[i] * prime[i] <= w[j]; j++) {
			ll k = w[j] / prime[i] <= sqr ? ind1[w[j] / prime[i]] : ind2[n / (w[j] / prime[i])];
			g1[j] -= prime[i] * (g1[k] - sp1[i - 1] + mod) % mod;
			g2[j] -= prime[i] * prime[i] % mod * (g2[k] - sp2[i - 1] + mod) % mod;
			g1[j] %= mod; g2[j] %= mod;
			if (g1[j] < 0)g1[j] += mod;
			if (g2[j] < 0)g2[j] += mod;
		}
	}
	printf("%lld\n", (S(n, 0) + 1) % mod); //f(1) = 1
}
posted @ 2020-09-21 15:10  —O0oO-  阅读(466)  评论(0编辑  收藏  举报