zoukankan      html  css  js  c++  java
  • 数论知识点

    网络赛数论板子题自闭

    特此开坑

    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
    }
    
  • 相关阅读:
    最短路小变形
    最短路
    bfs + 路径输出
    优先队列
    dijkstra
    重载运算符-operator
    最短路
    二分图匹配
    依赖型的关系建立
    string 类
  • 原文地址:https://www.cnblogs.com/sduwh/p/13705703.html
Copyright © 2011-2022 走看看