浅谈数学(二)
Furina_Aurora · · 算法·理论
前言
往期回顾
《浅谈数学》 by Stellar_River。
不得不说,SR 大佬也是太能肝了,把部分的中等数论都给写了。
编写人员
- 主编:Furina_Aurora;
- 副主编:Stellar_River & _m2b _\。
扩展欧几里得
本章由 Furina_Aurora 编写。
【前置】裴蜀定理
对于任意的两个不全为
特别地,
这一定理在上一期中已经介绍过了。
【例题】
:::info[题目描述]{open}
输入两个不同时为
::: :::success[解法]{open} 上一期提供的伪代码:
inline auto ExEuclid(auto a,auto b){
if(b==0)return abs(a),sign(a),0;
auto x1,y1;
x1=y1=g=ExEuclid(b,a%b);
x=y1;
y=x1-(a div b)*y1;
return g,x,y;
}
现在,我们给出了完整的代码:
inline int exgcd(int a,int b,int &x,int &y){
if(b==0){
x=(a>0?1:-1),y=0;
return abs(a);
}
int g=exgcd(b,a%b,x,y),tot=x;
x=y,y=tot-(a/b)*y;
return g;
}
:::
:::success[证明]{open}
情况
上一期中已经给出证明,本期不再赘述。
情况
我们不妨设
将
取
同理,若
情况
令
将
取
:::
欧拉函数
本章由 Stellar_River 编写。
【定义】
设
特别地,我们规定
【性质】
不妨设
- 积性函数:若
\gcd(m, n) = 1 ,则\varphi(mn) = \varphi(m)\varphi(n) ,可用中国剩余定理证明; - 素数幂的情形:
\varphi(p^k) = p^k - p^{k-1} = p^k \left(1 - \frac{1}{p}\right) - 一般公式:
若n = p_1^{\alpha_1} p_2^{\alpha_2} \cdots p_k^{\alpha_k} ,则\varphi(n) = \prod_{i=1}^k p_i^{\alpha_i} \left(1 - \frac{1}{p_i}\right) = n \prod_{i=1}^k \left(1 - \frac{1}{p_i}\right) - 高斯定理:
\sum_{d|n} \varphi(d) = n 证明:枚举因子
d ,恰好有\varphi(d) 个不超过n 的正整数k 满足\gcd(k, n) = \frac{n}{d} 【例题】GCD
:::info[题目描述]{open}
- 令
P 表示所有素数构成的集合; -
给定正整数 n ,求1\le x,y\le n 且\gcd(x,y) 为素数的数对(x,y) 有多少对。:::success[如何求解]{open} 设最终答案为 \text{ans} ,则$$ \begin{aligned} \text{ans} &= \sum{p \in P,p\leq n} \sum{i=1}^{n} \sum_{j=1}^{n} \llbracket \gcd(i, j) = p \rrbracket \ &= \sum{p \in P,p\leq n} \sum{i=1}^{\lfloor n/p \rfloor} \sum_{j=1}^{\lfloor n/p \rfloor} \llbracket \gcd(i, j) = 1 \rrbracket \ &= \sum{p \in P,p\leq n} \left( 2 \left( \sum{i=1}^{\lfloor n/p \rfloor} \sum_{j=1}^{i} \llbracket \gcd(i, j) = 1 \rrbracket \right) - 1 \right) \ &= \sum{p \in P,p\leq n} \left( 2 \left( \sum{i=1}^{\lfloor n/p \rfloor} \varphi(i) \right) - 1 \right) \end{aligned} $$ ::: ## 欧拉定理 本章由 Stellar_River 编写。 ### 【定义】欧拉定理 若 a, n \in \mathbb{Z}^+ 且\gcd(a, n) = 1 ,则$$ a^{\varphi(n)} \equiv 1 \pmod{n} $$ ### 【定义】费马小定理 若 a, p \in \mathbb{Z}^+ 且p 是素数,且p\nmid a ,则$$ a^{p-1} \equiv 1 \pmod{p} $$ ### 【推论】费马小定理 若 a, p \in \mathbb{Z}^+ 且p 是素数,且p\nmid a ,则$$ a^{-1} \equiv a^{p-2} \pmod{p} $$
因此,可以使用快速幂求模素数下的逆元。
【证明】欧拉定理
设
由于
在模
因此,这两个集合在模
即
每个
【定理】扩展欧拉定理
设
-
若
\gcd(a, m) = 1 ,则a^b \equiv a^{b \bmod \varphi(m)} \pmod{m} -
若
\gcd(a, m) \neq 1 且b < \varphi(m) ,则直接计算a^b \pmod{m} -
若
\gcd(a, m) \neq 1 且b \geq \varphi(m) ,则a^b \equiv a^{(b \bmod \varphi(m)) + \varphi(m)} \pmod{m}
Miller_Rabin
本章由 Furina_Aurora 编写。
【前置】素数判断
众所周知,我们判断一个数是否是素数,经常会用到以下代码:
inline bool isprime(int x){
if(x<=1) return false;
for(int i=2;i<x;i++){
if(x%i==0) return false;
}
return true;
}
然而上方的代码在判断如
inline bool isprime(int x){
if(x<=1) return false;
for(int i=2;1LL*i*i<=x;i++){
if(x%i==0) return false;
}
return true;
}
然而,你认为这还是太慢了,于是你引进了欧拉筛(伪代码):
int LinearSieve(int n){
memset(is_prime,true,sizeof is_prime);
is_prime[0]=is_prime[1]=false;
int tot=0;
for(int i=2;i<=n;i++){
if(is_prime[i])primes[tot++]=i;
for(int j=0;j<tot;j++){
if(1LL*primes[j]*i>n)break;
is_prime[primes[j]*i]=false;
if(i%primes[j]==0)break;
}
}
return tot;
}
那么除了上述的判断方式,有没有更快的方法呢?
有的有的,那就是 Miller-Rabin 素数测试!
【原理与定义】
Miller-Rabin 基于费马小定理实现,这个算法大致是这样的:
取一个序列
【例题】SP288
这是 Miller-Rabin 的模板题,这里我们给出代码。
:::success[代码]{open}
#include<bits/stdc++.h>
#define int long long
using namespace std;
int prime[]={2,325,9375,28178,450775,9780504,1795265022};
// 省略快读
inline int mul(int x,int y,int MOD){
return (unsigned __int128)(unsigned long long)x*(unsigned long long)y%MOD;
}
inline int qpow(int x,int y,int MOD){
int res=1;
while(y){
if(y&1)res=mul(res,x,MOD);
x=mul(x,x,MOD);
y>>=1;
}
return res;
}
inline bool Miller_Rabin(int n,int a){
int d=n-1,r=0;
while(!(d&1))d>>=1,r++;
int z=qpow(a,d,n);
if(z==1)return true;
for(int i=0;i<r;i++){
if(z==n-1)return true;
z=mul(z,z,n);
}
return false;
}
inline bool isprime(int n){
if(n<=1)return false;
for(int i=0;i<7;i++){
if(n==prime[i])return true;
if(prime[i]%n==0)continue;
if(!Miller_Rabin(n,prime[i]%n))return false;
}
return true;
}
inline void solve(){
int n=read();
if(isprime(n))cout<<"YES"<<'\n';
else cout<<"NO"<<'\n';
}
signed main(){
int T=read();
while(T--)solve();
return 0;
}
:::
Pollard-Rho
本章由 Stellar_River 编写。
【定义】
设
选取伪随机映射
从随机初值
:::info[生日悖论带来的关键观察]{open}
- 序列在模
n 下进入循环的期望长度为\mathcal O(\sqrt n) ; -
序列在模 p 下进入循环的期望长度仅为\mathcal O(\sqrt p)\leq\mathcal O(n^{\frac14}) 。
当序列在模
则
但
于是
此时给出
【\text{Floyd} 检测】
举一个生动的
不必存储整个序列,用双指针同时走:
每对
威尔逊定理
本章由 Furina_Aurora 编写。
【定义】
对于整数
【证明】
这里证明同余式成立时
又由 假设
然而
所以,
| 反过来,若 |
|---|
| ### 【推论】半阶乘平方公式 |
| 对于奇素数 |
| 举个例子: |
当
【推论】广义威尔逊
公式如下: 原公式不构成有效的数学命题,故暂不列出。
【推论】 威尔逊商公式
【推论】威尔逊素数
满足
莫比乌斯函数
本章由 Furina_Aurora 编写。
【积性函数】
我们设
-
f(1)=1 - 在正整数
a,b 互素条件下,f(ab)=f(a) \times f(b)
那么我们称这个函数
【狄利克雷卷积】
定义两个函数
【定义】
莫比乌斯函数
- 若
n=1 ,则\mu(1)=1 - 若存在素数
p 使得p^2\mid n ,则\mu(n)=0 - 若
n 没有平方因子,且n 是p 个质数的乘积,则\mu(n)=(-1)^p
【性质】
- 若
n=1 ,则\sum_{d \mid n} \mu(d)=1 - 否则,
\sum_{d\mid n}\mu(d)=0
:::success[证明]{open}
若
不妨设
其中
又
且此时
由二项式定理得,
得证。
| 注:由人工证明,但使用了 DeepSeek V4 整理证明过程。 |
|---|
| ## 莫比乌斯反演 |
| 本章由 Furina_Aurora 编写。 |
| ### 【定义】 |
| 我们设 |
| 则有: |
:::success[证明]{open}
将
因
我们固定
我们记
上方得式子等于
证毕。
| 注:由人工证明,但使用了 DeepSeek V4 整理证明过程。 |
|---|
【例题】P3455
感谢 DanseSolo 的建议,采用这道题作例题。
莫比乌斯反演板子题喵~
简化题意:求
代码就不放了。