数论知识点

网络赛数论板子题自闭

特此开坑

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)

( ightarrow varphi * I * mu = id * mu)

( ightarrow 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) = egin{cases} 1 , ext{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 ]

(xin[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) = nprod_{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})) ]

[= nprod_{i=1}^{i = k}(1-frac1{p_i}) ]

证毕

性质五:

(i mod p = 0)

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

(i mod p eq 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)(kin Z)((k)可以是负数)

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

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

欧拉定理:

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

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

广义欧拉定理

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

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

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

3. 莫比乌斯函数

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

[mu(x)= egin{cases}1,& ext{x = 1}\0,& ext{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{k_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})\ o =sum_{d=1}^{n}g(d)cdotsum_{i=1}^{lfloorfrac{n}{d} floor}f({i}) ]

[ o sum_{i=1}^{n}h(i)=sum_{d=1}^{n}g(d)cdot S(lfloorfrac{n}{d} floor) ]

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

[sum_{i=1}^{n}h(i)=g(1)cdot S(n)+sum_{d=2}^{n}g(d)cdot S(lfloorfrac{n}{d} floor) ]

[ o g(1)S(n)=sum_{i=1}^{n}h(i)-sum_{d=2}^{n}g(d)cdot S(lfloorfrac{n}{d} floor) ]

9. min25筛

min25模板

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

适用条件:

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

思想:

[sum_{i=1}^nf(i) = sum_{i in Prime}f(i) + sum_{i otin 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^kigg(g(dfrac n {P_j},j-1) -g(P_j-1,j-1)igg) ]

这个东西自己在纸上写一些体会一下,注意 (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)igg(S igg(dfrac n {p_k^e}igg) + [e e 1]igg) ]

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

存下所有可能的 (lfloordfrac n x floor) , 做一个映射

[idx(x)= egin{cases}ind1[x] , xle sqrt n \ind2[n/x], x>sqrt nend{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
", (S(n, 0) + 1) % mod); //f(1) = 1
}
原文地址:https://www.cnblogs.com/sduwh/p/13705703.html