Typesetting math: 52%

数论笔记-同余

同余

带余数除法

带余数除法的定义与基本性质

定义 对于整数 a,ba,bb0b0 ,一定存在整数 q,rq,r 满足 a=qb+ra=qb+r ,其中 r[0,b)r[0,b) ,称 qqaa 除以 bb 的商, rraa 除以 bb 的余数。

注意,c++的 % 模运算指定 rraa 同号, / 整除运算指定正数取下整、负数取上整,都需要辨别。

模运算的定义 amodbamodb 的结果为 aa 除以 bb 的余数 rr ,运算优先级同乘除。

mm 加法 (a+b)modm(a+b)modm

mm 减法 (ab)modm(ab)modm

mm 乘法 abmodmabmodm

性质1 模运算与整除的关系

{abab,b>0abab,b<0abab,b>0abab,b<0

性质2 模运算的运算规律

(amodm±bmodm)modm=(a±b)modm(amodm)(bmodm)modm=abmodm(amodm)kmodm=akmodm,kN(amodm±bmodm)modm=(a±b)modm(amodm)(bmodm)modm=abmodm(amodm)kmodm=akmodm,kN

性质3 amodn=amodm=xamodn=amodm=xgcd(n,m)=1gcd(n,m)=1 ,则 amodnm=xamodnm=x

性质3的证明:

由同余式可得 ax=k1n=k2max=k1n=k2m ,又 gcd(n,m)=1gcd(n,m)=1 ,根据整除基本性质4,所以 mk1nmk1mk1nmk1 ,所以设 k1=k3mk1=k3m ,于是 ax=k3mnax=k3mn ,即 amodnm=xamodnm=x

模运算加速算法

模运算封装

强大模板,告别打 % 打到手酸。

常数较大。

时间复杂度

  1. 求幂 O(logk)O(logk)
  2. 逆元 O(logP)O(logP)
  3. 其余 O(1)O(1)

空间复杂度 O(1)O(1)

template<int P>
struct ModInt {
int val;
ModInt(ll _val = 0) {
if (2 * P <= _val) val = _val % P;
else if (P <= _val) val = _val - P;
else if (0 <= _val) val = _val;
else if (-P <= _val) val = _val + P;
else val = (_val % P + P) % P;
}
// 快速幂
ModInt qpow(ll k) const {
ModInt a = *this, ans = 1;
while (k) {
if (k & 1) ans = ans * a;
k >>= 1;
a = a * a;
}
return ans;
}
// 矩阵初等变换求逆
ModInt inv() const {
int a = val, b = P, u = 1, v = 0;
while (b) {
int t = a / b;
swap(a -= t * b, b);
swap(u -= t * v, v);
}
return { u };
}
ModInt &operator+=(const ModInt &x) { val + x.val >= P ? val += x.val - P : val += x.val; return *this; }
ModInt &operator-=(const ModInt &x) { val - x.val < 0 ? val -= x.val - P : val -= x.val; return *this; }
ModInt &operator*=(const ModInt &x) { val = 1LL * val * x.val % P; return *this; }
ModInt &operator/=(const ModInt &x) { return val % x.val == 0 ? val /= x.val, *this : *this *= x.inv(); }
friend ModInt operator+(ModInt a, const ModInt &b) { return a += b; }
friend ModInt operator-(ModInt a, const ModInt &b) { return a -= b; }
friend ModInt operator*(ModInt a, const ModInt &b) { return a *= b; }
friend ModInt operator/(ModInt a, const ModInt &b) { return a /= b; }
friend ModInt operator-(const ModInt &x) { return { -x.val }; }
friend bool operator==(const ModInt &a, const ModInt &b) { return a.val == b.val; }
friend bool operator!=(const ModInt &a, const ModInt &b) { return a.val != b.val; }
friend istream &operator>>(istream &is, ModInt &x) {
ll _x;
is >> _x;
x = { _x };
return is;
}
friend ostream &operator<<(ostream &os, const ModInt &x) { return os << x.val; }
};
using MInt = ModInt<P>;

龟速乘

用于可能爆 long long 数字的乘法取余。

不过一般可以用 __int128 替代了。

时间复杂度 O(logb)O(logb)

空间复杂度 O(1)O(1)

const int P = 1e9 + 7;
ll qmul(ll a, ll b) {
ll ans = 0;
while (b) {
if (b & 1) ans = (ans + a) % P;
b >>= 1;
a = (a << 1) % P;
}
return ans;
}

快速幂

常用的整数幂次取余,aa 越大速度越慢。

时间复杂度 O(logk)O(logk)

空间复杂度 O(1)O(1)

const int P = 1e9 + 7;
int qpow(int a, ll k) {
int ans = 1;
while (k) {
if (k & 1) ans = 1LL * ans * a % P;
k >>= 1;
a = 1LL * a * a % P;
}
return ans;
}

同余的定义与基本性质

定义 若整数 a,ba,bmm 的余数相等,则称 a,ba,bmm 同余,记作 ab(modm)ab(modm) 。若余数不等,则称 a,ba,bmm 不同余,记作 ab(modm)a≢b(modm)

约定 由于对负模数 mm 的讨论等价于正模数的讨论,所以若不特殊指明,我们假定模数 m>0m>0

性质1(自反性) aa(modm)aa(modm)

性质2(对称性) ab(modm)ba(modm)ab(modm)ba(modm)

性质3(传递性) ab(modm) 且 bc(modm)ac(modm)ab(modm)  bc(modm)ac(modm)

性质4(同加性)

ab(modm)a±cb±c(modm)ab(modm),cd(modm)a±cb±d(modm)ab(modm)a±cb±c(modm)ab(modm),cd(modm)a±cb±d(modm)

性质5(同乘性)

ab(modm)acbc(modm)ab(modm),cd(modm)acbd(modm)ab(modm)acbc(modm)ab(modm),cd(modm)acbd(modm)

性质6(同幂性) ab(modm)akbk(modm)ab(modm)akbk(modm) ,其中 k0k0

性质7(同除性) ab(modm)adbd(modmgcd(m,d))ab(modm)adbd(modmgcd(m,d)) ,其中 dd 满足 da,dbda,db

性质8ab(modm)ab(modm) ,那么 mmab(modm)mmab(modm)

性质9 ab(modmi)(i=1,2,,k)ab(modM)ab(modmi)(i=1,2,,k)ab(modM) ,其中 M=lcm(m1,m2,,mk)M=lcm(m1,m2,,mk)

性质10 ab(modm)gcd(a,m)=gcd(b,m)ab(modm)gcd(a,m)=gcd(b,m)

性质9的证明:

ab(modmi)(i=1,2,,k)ab(modmi)(i=1,2,,k) 可得 miabmiab ,根据整除基本性质11,可得 Mab,M=lcm(m1,m2,,mk)Mab,M=lcm(m1,m2,,mk) ,因此 ab(modM)ab(modM)

同余类与剩余系的定义与基本性质

同余类的定义 对于 a[0,m1]a[0,m1] ,集合 {a+km},kZ{a+km},kZ 的所有数模 mm 同余 aa ,称这个集合为模 mm 的一个同余类 ¯a¯¯¯a

完全剩余系的定义mm 的同余类有 mm 个,分别为 ¯0,¯1,,¯m1¯¯¯0,¯¯¯1,,¯¯¯¯¯¯¯¯¯¯¯¯¯¯m1 ,它们构成了 mm 的完全剩余系。

既约剩余系的定义mm 的同余类有 φ(m)φ(m) 个的代表元与 mm 互质,它们构成了 mm 的既约剩余系(简化剩余系)。

φ(m)φ(m) 为欧拉函数,下一节会讲到。

性质1SS 是模 mm 的一个完全剩余系,若 gcd(k,m)=1gcd(k,m)=1 ,则 S={xx=kx+b,xS}S={xx=kx+b,xS} 也是模 mm 的一个完全剩余系。

性质2 设模 m1m1 的完全剩余系为 S1S1 ,模 m2m2 的完全剩余系为 S2S2 ,且 gcd(m1,m2)=1gcd(m1,m2)=1 ,则模 m=m1m2m=m1m2 的完全剩余系为 S={xx=m2x1+m1x2,x1S1,x2S2}S={xx=m2x1+m1x2,x1S1,x2S2}

性质3SS 是模 mm 的一个既约剩余系,若 gcd(k,m)=1gcd(k,m)=1 ,则 S={xx=kx,xS}S={xx=kx,xS} 也是模 mm 的一个既约剩余系。

性质4 设模 m1m1 的既约剩余系为 S1S1 ,模 m2m2 的既约剩余系为 S2S2 ,且 gcd(m1,m2)=1gcd(m1,m2)=1 ,则模 m=m1m2m=m1m2 的既约剩余系为 S={xx=m2x1+m1x2,x1S1,x2S2}S={xx=m2x1+m1x2,x1S1,x2S2}

  • 推论1(性质4的推论) gcd(m1,m2)=1φ(m1m2)=φ(m1)φ(m2)gcd(m1,m2)=1φ(m1m2)=φ(m1)φ(m2) ,即欧拉函数是积性函数。

性质1的证明:

假设存在 kxi+bkxj+b(modm)kxi+bkxj+b(modm) ,则 kxikxj(modm)kxikxj(modm) 。因为 gcd(k,m)=1gcd(k,m)=1 ,所以 xixj(modm)xixj(modm)xi,xjxi,xj 属于一个同余类,矛盾。综上,得证。

性质2的证明:

假设存在 m2x1+m1x2m2x1+m1x2(modm)m2x1+m1x2m2x1+m1x2(modm) ,那么 m2(x1x1)m1(x2x2)(modm)m2(x1x1)m1(x2x2)(modm) 。因为 m1mm1m ,所以 m2(x1x1)m1(x2x2)0(modm1)m2(x1x1)m1(x2x2)0(modm1) ,又 gcd(m1,m2)=1gcd(m1,m2)=1 ,所以 x1x10(modm1)x1x10(modm1) ,矛盾。综上,得证。

性质3的证明:

根据性质1证明,类似可得 SS 一定是 mm 的一个剩余系,且有 φ(m)φ(m) 个元素,接下来只需证明任意元素都与 mm 互质。

任意 xSxS ,有 gcd(x,m)=1gcd(x,m)=1 ,又 gcd(k,m)=1gcd(k,m)=1 ,所以 gcd(kx,m)=1gcd(kx,m)=1 ,所以 SS 是模 mm 的既约剩余系。

性质4的证明:

根据性质2证明,类似可得 SS 一定是模 mm 的一个剩余系,且有 φ(m1)φ(m2)φ(m1)φ(m2) 个元素,但我们并不知道 φ(m1)φ(m2)=φ(m1m2)φ(m1)φ(m2)=φ(m1m2) ,因此我们证明 SS 的元素都与 mm 互质只能说明 SS 是模 mm 的既约剩余系的一个子集,我们还需要证明模 mm 的既约剩余系是 SS 的一个子集。

gcd(x1,m1)=gcd(x2,m2)=1gcd(x1,m1)=gcd(x2,m2)=1 ,又 gcd(m1,m2)=1gcd(m1,m2)=1 ,因此 gcd(m2x1,m1)=gcd(m1x2,m2)=1gcd(m2x1,m1)=gcd(m1x2,m2)=1 ,所以 gcd(m2x1+m1x2,m1)=gcd(m1x2+m2x1,m2)=1gcd(m2x1+m1x2,m1)=gcd(m1x2+m2x1,m2)=1 ,于是 gcd(m1x2+m2x1,m1m2)=1gcd(m1x2+m2x1,m1m2)=1 ,即 SS 是模 mm 的既约剩余系的子集。

因为 gcd(m1,m2)=1gcd(m1,m2)=1 ,因此 m2x1+m1x2m2x1+m1x2 可以表达所有整数。那么令模 mm 的既约剩余系的元素为 m2x1+m1x2m2x1+m1x2 ,则 gcd(m2x1+m1x2,m1m2)=1gcd(m2x1+m1x2,m1m2)=1 ,因此 gcd(m2x1+m1x2,m1)=gcd(m2x1+m1x2,m2)=1gcd(m2x1+m1x2,m1)=gcd(m2x1+m1x2,m2)=1 ,所以 gcd(m2x1,m1)=gcd(m1x2,m2)=1gcd(m2x1,m1)=gcd(m1x2,m2)=1 ,又 gcd(m1,m2)=1gcd(m1,m2)=1 ,于是 gcd(x1,m1)=gcd(x2,m2)=1gcd(x1,m1)=gcd(x2,m2)=1 ,即模 mm 的既约剩余系是 SS 的子集。

综上 SS 就是模 mm 的既约剩余系。

推论1的证明:

由性质4,可得 SS 的元素个数是 φ(m1)φ(m2)φ(m1)φ(m2) ,而模 mm 的既约剩余系的元素个数是 φ(m1m2)φ(m1m2) 。因此,当 gcd(m1,m2)=1gcd(m1,m2)=1φ(m1m2)=φ(m1)φ(m2)φ(m1m2)=φ(m1)φ(m2) ,即欧拉函数是积性函数。

欧拉函数

欧拉函数的定义与基本性质

定义 [1,n][1,n] 中与 nn 互质的个数记作 φ(n)φ(n) ,称为欧拉函数。

性质1 φ(p)=p1φ(p)=p1 ,其中 pp 为素数。

性质2 φ(pk)=pkpk1φ(pk)=pkpk1 ,其中 kZ+kZ+pp 为素数。

性质3 欧拉函数是积性函数,即 gcd(a,b)=1φ(ab)=φ(a)φ(b)gcd(a,b)=1φ(ab)=φ(a)φ(b)

性质4(欧拉函数的展开式) φ(n)=npn(11p)φ(n)=npn(11p)

性质5 pn 且 p2nφ(n)=(p1)φ(np)pn  p2nφ(n)=(p1)φ(np) ,其中 pp 为素数。

性质6 p2nφ(n)=pφ(np)p2nφ(n)=pφ(np) ,其中 pp 为素数。

性质4的证明:

由性质3直接可得

φ(n)=φ(ki=1pcii)=ki=1φ(pcii)=ki=1(pciipci1i)=npn(11p)φ(n)=φ(ki=1pcii)=ki=1φ(pcii)=ki=1(pciipci1i)=npn(11p)

其中 pp 是素数。

性质3是由同余类部分证明得到的,比较困难。实际上,我们还能使用容斥原理直接证明,更加简单。

由此还能得出性质5和6。

欧拉函数的求法

试除法

利用试除法的分解质因子,通过性质4累乘即可,适用于只求单个欧拉函数的值。

可以提前 O(n)O(n) 预处理素数,时间复杂度 O(nlnn)O(nlnn) ,空间复杂度 O(n)O(n)

时间复杂度 O(n)O(n)

空间复杂度 O(1)O(1)

int one_euler(int n) {
int ans = n;
for (int i = 2;i * i <= n;i++) {
if (!(n % i)) {
ans = ans / i * (i - 1);
while (!(n % i)) n /= i;
}
}
if (n > 1)ans = ans / n * (n - 1);
return ans;
}

线性筛求欧拉函数

对于素数 pp ,直接令 φ(p)=p1φ(p)=p1

对于合数 nn ,因为只会在 i=npi=np 时被最小质因子 pp 筛一次,因此我们可以递推,但需要分类讨论:

  1. ppii 的最小质因子小,满足性质5,因此 φ(n)=φ(p)φ(i)=(p1)φ(i)φ(n)=φ(p)φ(i)=(p1)φ(i)
  2. ppii 的最小质因子,满足性质6, φ(n)=pφ(i)φ(n)=pφ(i)

时间复杂度 O(n)O(n)

空间复杂度 O(n)O(n)

const int N = 1e7 + 7;
bool vis[N];
vector<int> prime;
int phi[N];
void get_euler(int n) {
phi[1] = 1;
for (int i = 2;i <= n;i++) {
if (!vis[i]) {
prime.push_back(i);
phi[i] = i - 1;
}
for (auto j : prime) {
if (i * j > n) break;
vis[i * j] = 1;
if (!(i % j)) {
phi[i * j] = j * phi[i];
break;
}
phi[i * j] = (j - 1) * phi[i];
}
}
}

欧拉函数的其他性质

性质1n3n3 时,φ(n)φ(n) 为偶数。

性质2 f(n)=ni=1[gcd(i,k)=1]=nkφ(n)+f(nmodk)f(n)=ni=1[gcd(i,k)=1]=nkφ(n)+f(nmodk)

性质3 ni=1i[gcd(i,n)=1]=nφ(n)+[n=1]2ni=1i[gcd(i,n)=1]=nφ(n)+[n=1]2

性质4 dnφ(d)=ndnφ(d)=n

性质5 φ(ab)=φ(a)φ(b)gcd(a,b)φ(gcd(a,b))φ(ab)=φ(a)φ(b)gcd(a,b)φ(gcd(a,b))

性质6 d2nφ(n)=dφ(nd)d2nφ(n)=dφ(nd)

  • 推论1(性质5、6的推论)n=abdk,k2n=abdk,k2gcd(a,b)=1gcd(a,b)=1 ,则 φ(n)=dk2φ(abd2)=dk2φ(ad)φ(bd)dφ(d)φ(n)=dk2φ(abd2)=dk2φ(ad)φ(bd)dφ(d)

性质1的证明:

对于 n3n3 ,当 m<nm<n ,若 gcd(m,n)=1gcd(m,n)=1 ,则 gcd(nm,n)=1gcd(nm,n)=1 ,同时 mnmmnm

因此每一个与 nn 互质的数 mm 都对应一个 nmnm 也与 nn 互质,所以 φ(n)φ(n) 为偶数。

性质2的证明:

f(n)f(n) 等同于 [1,n][1,n] 中与 kk 互质的数的个数。

我们把 [1,n][1,n]kk 个数分一段,能分完整的 nknk 段,以及 nmodknmodk 个多出来的数。

根据 gcd(a,b)=gcd(amodb,b)gcd(a,b)=gcd(amodb,b) ,因此 [1+mk,k+mk][1+mk,k+mk] 中与 kk 互质的数等于 [1,k][1,k] 中与 kk 互质的数,因此完整的 nknk 段中,共有 nkφ(k)nkφ(k) 个与 kk 互质的数。而 [1+nkk,n][1+nkk,n] 中与 kk 互质的数等于 [1,nmodk][1,nmodk] 中与 kk 互质的数,即 f(nmodk)f(nmodk)

综上 f(n)=ni=1[gcd(i,k)=1]=nkφ(n)+f(nmodk)f(n)=ni=1[gcd(i,k)=1]=nkφ(n)+f(nmodk)

性质3的证明:

左式等同于 [1,n][1,n] 中与 nn 互质的数的和。

n3n3 时,根据性质 11 ,互质的数一定形如 m,nmm,nm 成对出现,因此总和的平均值为 n2n2 ,因此总和为 nφ(n)2nφ(n)2

n=2n=2 时,上式也成立。

n=1n=1 时,上式结果为 1212 ,因此增加修正 [n=1]2[n=1]2

综上, ni=1i[gcd(i,n)=1]=nφ(n)+[n=1]2ni=1i[gcd(i,n)=1]=nφ(n)+[n=1]2

性质4的证明:

f(x)=ni=1[gcd(i,n)=x]f(x)=ni=1[gcd(i,n)=x] ,则 ni=1f(i)=nni=1f(i)=n ,这是因为每个数的 gcdgcd 唯一,遍历一遍 gcdgcd 能覆盖 nn

gcd(i,n)=dgcd(id,nd)=1gcd(i,n)=dgcd(id,nd)=1 ,所以当 xnxn 时, f(x)=nxi=1[gcd(i,nx)=1]=φ(nx)f(x)=nxi=1[gcd(i,nx)=1]=φ(nx) ;当 xnxn 时, f(x)=0f(x)=0

综上 dnφ(d)=dnφ(nd)=dnf(d)=ni=1f(i)=ndnφ(d)=dnφ(nd)=dnf(d)=ni=1f(i)=n

性质5的证明:

根据基本性质5可得

φ(ab)=abpab(11p)=apa(11p)bpb(11p)papb(11p)=φ(a)φ(b)gcd(a,b)gcd(a,b)pgcd(a,b)(11p)=φ(a)φ(b)gcd(a,b)φ(gcd(a,b))φ(ab)=abpab(11p)=apa(11p)bpb(11p)papb(11p)=φ(a)φ(b)gcd(a,b)gcd(a,b)pgcd(a,b)(11p)=φ(a)φ(b)gcd(a,b)φ(gcd(a,b))

性质6的证明:

因为 d2nd2n ,所以 nnndnd 的质因子相同,因此 φ(n)=npn(11p)=dndpnd(11p)=dφ(nd)φ(n)=npn(11p)=dndpnd(11p)=dφ(nd)

同余重要定理

费马小定理

定理1(费马小定理)pp 为质数且整数 aa 不是 pp 的倍数,则 ap11(modp)ap11(modp)

  • 推论1(定理1的推论,费马降幂)pp 为质数且整数 aa 不是 pp 的倍数,则 ananmod(p1)(modp)ananmod(p1)(modp)

定理2(费马大定理) 若整数 n3n3 ,则 xn+yn=znxn+yn=zn 无正整数解。

定理1的证明:

由欧拉定理可得, φ(p)=p1φ(p)=p1 ,且 gcd(a,p)=1gcd(a,p)=1 ,因此 ap11(modp)ap11(modp)

欧拉定理见下一节。

定理2的证明:

我有一个绝妙的证明方法,但这里地方太小了我写不下qwq。

欧拉定理

定理1(欧拉定理)gcd(a,m)=1gcd(a,m)=1,则 aφ(m)1(modm)aφ(m)1(modm)

  • 推论1(定理1的推论) gcd(a,m)=1xZ+,axmodm=1gcd(a,m)=1xZ+,axmodm=1

定理2(拓展欧拉定理,欧拉降幂)

ab{abmodφ(m),gcd(a,m)=1ab,b<φ(m) 且 gcd(a,m)1abmodφ(m)+φ(m),bφ(m) 且 gcd(a,m)1(modm)ab⎪ ⎪⎪ ⎪abmodφ(m),gcd(a,m)=1ab,b<φ(m)  gcd(a,m)1abmodφ(m)+φ(m),bφ(m)  gcd(a,m)1(modm)

定理1的证明:

{x1,x2,,xφ(m)}{x1,x2,,xφ(m)} 是一个模 mm 的既约剩余系。

根据同余类与剩余系基本性质3,因为 gcd(a,m)=1gcd(a,m)=1 ,所以 {ax1,ax2,,axφ(m)}{ax1,ax2,,axφ(m)} 也是模 mm 的一个既约剩余系。因此, x1x2xφ(m)aφ(m)x1x2xφ(m)(modm)x1x2xφ(m)aφ(m)x1x2xφ(m)(modm)

gcd(x1,m)==gcd(xφ(m),m)=1gcd(x1,m)==gcd(xφ(m),m)=1 ,所以 gcd(x1x2xφ(m),m)=1gcd(x1x2xφ(m),m)=1 ,于是 aφ(m)1(modm)aφ(m)1(modm)

推论1的证明:

从左到右,由条件 xN+,gcd(ax,m)=gcd(axmodm,m)=gcd(1,m)=1xN+,gcd(ax,m)=gcd(axmodm,m)=gcd(1,m)=1 ,所以 gcd(ax,m)=gcd(a,m)=1gcd(ax,m)=gcd(a,m)=1

从右到左,根据欧拉定理显然。

定理2的证明:

见此链接

威尔逊定理

pp 修正阶乘的定义pp 为素数,去除 n!n! 能被 pp 整除的数字的剩下部分,即 ni=1,(i,p)=1ini=1,(i,p)=1i ,称为 nnpp 修正阶乘,记作 (n!)p(n!)p

定理1pp 为素数, nn 为正整数,则 n!=(n!)pn/p!pn/pn!=(n!)pn/p!pn/p

定理2pp 为素数, nn 为正整数,则 n!pvp(n!)=n/p!pvp(n/p!)(n!)pn!pvp(n!)=n/p!pvp(n/p!)(n!)p

定理3pp 为素数, n,αn,α 为正整数,则 (n!)p(pα!)n/pαp((nmodpα)!)p(modpα)(n!)p(pα!)n/pαp((nmodpα)!)p(modpα)

定理4(威尔逊定理) 当且仅当 pp 为素数, (p1)!1(modp)(p1)!1(modp)

定理5(扩展威尔逊定理)pp 为素数, αα 为正整数,那么 (pα!)p{1,p=2 and α31,otherwise(modpα)(pα!)p{1,p=2 and α31,otherwise(modpα)

  • 推论1(定理2、3、5的推论)pp 为素数, n,αn,α 为正整数, n!pvp(n!)(±1)n/pαn/p!pvp(n/p!)((nmodpα)!)p(modpα)n!pvp(n!)(±1)n/pαn/p!pvp(n/p!)((nmodpα)!)p(modpα)

定理1的证明:

n!=(p1)!×p×(2p1)!(p)!×2p××(n/pp1)!((n/p1)p)!×n/pp×n!(n/pp)!n!=(p1)!×p×(2p1)!(p)!×2p××(n/pp1)!((n/p1)p)!×n/pp×n!(n/pp)! ,因此 n!=(n!)pn/p!pn/pn!=(n!)pn/p!pn/p

定理2的证明:

根据定理1可以得到 n!=(n!)pn/p!pn/pn!=(n!)pn/p!pn/p ,再根据勒让德定理的推论1可以得到 vp(n!)=n/p+vp(n/p!)vp(n!)=n/p+vp(n/p!) ,因此有 n!pvp(n!)=n!pn/ppvp(n/p!)=n/p!pvp(n/p!)(n!)pn!pvp(n!)=n!pn/ppvp(n/p!)=n/p!pvp(n/p!)(n!)p

定理3的证明:

我们可以以 pαpα 为一个周期划分 (n!)p(n!)p ,可以发现共有 npαnpα 部分且都同余第一部分 (pα!)p(pα!)p ,剩下的同余 ((nmodpα)!)p((nmodpα)!)p ,因此可以得到 (n!)p(pα!)n/pαp((nmodpα)!)p(modpα)(n!)p(pα!)n/pαp((nmodpα)!)p(modpα)

定理4的证明:

充分性:

pp 不是素数,分类讨论:

  1. p=4p=4 时, (41)!2(mod4)(41)!2(mod4) ,显然不成立。
  2. p=ab(ab)p=ab(ab) 时,由于 a,b<pa,b<p ,所以 (p1)!kab0(modp)(p1)!kab0(modp)
  3. p=a2(a>2)p=a2(a>2) 时,有 a,2a<aa=pa,2a<aa=p ,所以 (p1)!=2ka20(modp)(p1)!=2ka20(modp)

所以 pp 必为素数。

必要性:

pp 为素数,则 [1,p1][1,p1] 的整数必存在唯一逆元。因此,对于 x[1,p1]x[1,p1] ,其逆元 x1x1 若不等于 x ,则可以相互配对可得 xx11(modp) ,考虑 x21(modp) 的情况。

设任意 x,y[1,p1]xy ,满足 x2y21(modp) ,那么有 x2y2(x+y)(xy)0(modp) ,其中一定有 pxy ,于是 px+y ,所以一定有 x+y=p ,显然只有 1,p1 满足。

因此, (p1)!p11(modp)

综上得证。

定理5的证明:

与威尔逊定理必要性证明类似,即配对逆元,再考虑 x21(modpα) 解的情况。

我们对 x21(modpα) 解的情况分类讨论:

  1. p=2α=1 时,仅有一解 1
  2. p=2α3 时,有四解 ±1,2q1±1
  3. 其余情况,均有两解 ±1

因此可以得到 (n!)pmodpq 的所有情况。

推论1的证明:

由定理2可得 n!pvp(n!)=n/p!pvp(n/p!)(n!)p ,再有定理3可得 (n!)p(pα!)n/pαp((nmodpα)!)p(modpα) ,最后根据定理5可得 (pα!)p±1(modpα) 可根据具体情况判断,最后 n!pvp(n!)(±1)n/pαn/p!pvp(n/p!)((nmodpα)!)p(modpα)

二元一次不定方程

二元一次不定方程的定义与基本性质

定义 关于整数 x,y 的方程 ax+by=c ,其中 a,b,c 都是整数且 a,b 不为 0 ,称为二元一次不定方程。

裴蜀定理

定理1(裴蜀定理) 关于整数 x,y 不定方程 ax+by=c 有解的充要条件是 gcd(a,b)c

  • 推论1 关于整数 x,y 不定方程 ax+by=1 有解的充要条件是 gcd(a,b)=1

定理2 关于整数 x,y 不定方程 ax+by=c ,满足 d=gcd(a,b),dc ,的所有解为

{x=x0+kbdy=y0kad

其中 (x0,y0) 是方程的特解, kZ

定理1的证明:

d=gcd(a,b) ,则 dax+by ,设 sax+by 的最小正值。

根据带余数除法,可得 a=qs+r ,则 r=aqs=aq(ax+by)=a(1qx)+b(qy) ,即 r 也可以被 ax+by 表示。

因为 r[0,s1] ,所以 r=0 ,即 sa ,同理 sb 。因此,sd ,所以 sd

因为 s=ax+by ,所以 ds , 于是 ds

综上 d=s ,即 gcd(a,b)=dax+by 的最小正值。

定理2的证明:

有特解 (x0,y0) ,设任意解为 (x,y) ,则 ax0+by0=ax+by=c ,于是有 a(xx0)=b(y0y) 。两边同时除以 d ,得到 ad(xx0)=bd(y0y) ,其中 gcd(ad,bd)=1 ,于是 ady0y,bdxx0 。因此有

{x=x0+kbdy=y0kad

其中 kZ

解二元一次不定方程

从数学角度,二元一次不定方程系数是整数范围的,但使用算法时我们需让 a,b0 ,详见整除章节 gcd 的求法前言。若出现如 a<0 等系数为负数情况,需转换为 |a|(x)+by=gcd(a,b) 求解。以下的证明建立在正系数之上。

扩展欧几里得算法

对于二元一次不定方程的求解,关键在于求出一组特解。扩展欧几里得算法(extended gcd,exgcd)在辗转相除法的基础上,递归求解关于 x,y 的方程 ax+by=gcd(a,b) 的一组特解。

证明:

考虑方程 ax+by=gcd(a,b)=gcd(b,abab)=bx+(abab)y

我们可以得到 ax+by=ay+b(xaby) ,于是得到

{x=yy=xaby

递归至 b=0 ,此时 ax+0y=gcd(a,0)=a ,易得 x=1,y=0 是一组解,就可以回溯求解。

通过exgcd求出一组特解以后,即可通过裴蜀定理中的定理2得到所有解。

可以证明exgcd的解 (x,y) 满足 |x|b,|y|a ,所以在 int 范围内可以都用 int 变量,详见OI-wiki。

以下只提供exgcd的算法。

时间复杂度 O(log(min{a,b}))

空间复杂度 O(1)

int exgcd(int a, int b, int &x, int &y) {
if (!b) { x = 1, y = 0; return a; }
int d = exgcd(b, a % b, x, y);
x -= (a / b) * y, swap(x, y);
return d;
}

二元一次不定方程的非负整数解

我们仅讨论 a,b,c1gcd(a,b)=1 的情况下,方程 ax+by=c 的非负整数解,即 x,y0 的解。

性质1c>abab ,则 ax+by=c 存在非负整数解。

性质2c=abab ,则 ax+by=c 不存在非负整数解。

性质3c<abab ,则 ax+by=c 恰好有 max{0,(a1)(b1)22}c 有非负整数解,且解唯一。

性质1的证明:

对于 x[0,b1]by=cax>ababaxababa(b1)=b ,所以 y0

所以方程有非负解。

性质2的证明:

ax+by=abab ,即 a(x+1)+b(y+1)=ab 。因为 gcd(a,b)=1 ,所以 ay+1,bx+1

ka=y+1,mb=x+1 ,其中 k,mZ+ 。代入原式得, (m+k)ab=ab ,所以 m+k=1 ,所以必有一个小于等于 0 ,即 x,y 中必有一个小于 0 ,因此没有非负解。

性质3的证明:

分三步证明。

  1. ax+by=c 有非负解,则解 (x,y)[0,b2]×[0,a2](x,y)(0,0),(b2,a2)

    因为 y0 ,所以 ax=cbyc<abab ,所以 x<b1ba ,即 xb2

    同理 ya2

    (x,y)(0,0),(b2,a2) 可以验证得到。

  2. ax+by=c 有非负解,则最多只有一个非负解。

    (x0,y0) 是一个非负解,则 x0[0,b2],y0[0,a2] 。因为 gcd(a,b)=1 ,所以通解为

    {x=x0+kby=y0ka

    其他解一定不在 [0,b2]×[0,a2] 中,一定不是解,因此只有一个非负解。

  3. (x,y)[0,b2]×[0,a2](x,y)(0,0),(b2,a2)(x,y)ax+by=c 的一个非负解,当且仅当 (b2x,a2y) 不是任何 c<abab 的非负解。

    必要性:

    ax+by=c<abab ,所以

    a(b2x)+b(a2y)=ab2aax+ab2bby=2(abab)(ax+by)>abab

    因此 (b2x,a2y) 不是任何 c<abab 的非负解。

    充分性:

    因为 (b2x,a2y) 不是任何 c<abab 的非负解,且 a(b2x)+b(a2y)>0 以及 c=abab 没有非负解,因此 a(b2x)+b(a2y)>abab ,所以

    a(b2x)+b(a2y)=ab2aax+ab2bby=2(abab)(ax+by)>abab

    于是 ax+by<abab ,又 ax+by>0 ,所以 (x,y) 一定是 c<abab 的一个非负解。

综上,当 c<abab 时,

由1得知,解一定出现在 (x,y)[0,b2]×[0,a2](x,y)(0,0),(b2,a2)

由3得知,有解和无解一定成对出现,所以共 max{0,(a1)(b1)22} 个解。

由2得知,解和 c 是一一对应的,所以共 max{0,(a1)(b1)22}c 有解。

乘法逆元

乘法逆元的定义与基本性质

定义 当且仅当 gcd(a,m)=1 时,存在整数 x 满足 ax1(modm) ,我们称 xa 在模 m 意义下的逆元,记作 a1

乘法逆元的求法

费马小定理法

m 为质数且整数 a 不是 m 的倍数,则 am1aam21(modm) ,其中 am2 即为所求逆元。

时间复杂度 O(logm)

空间复杂度 O(1)

const int P = 1e9 + 7;
int qpow(int a, ll k) {
int ans = 1;
while (k) {
if (k & 1) ans = 1LL * ans * a % P;
k >>= 1;
a = 1LL * a * a % P;
}
return ans;
}
int inv(int x) { return qpow(x, P - 2); }

扩展欧几里得算法

gcd(a,m)=1 ,那么 ax1(modm)ax+my=1 一定存在解,即一定有 a 在模 m 意义下的逆元 a1=x 。因此,我们可以解 ax+my=1 ,利用exgcd可以直接求解。

时间复杂度 O(log(min{a,m}))

空间复杂度 O(1)

const int P = 1e9 + 7;
int exgcd(int a, int b, int &x, int &y) {
if (!b) { x = 1, y = 0; return a; }
int d = exgcd(b, a % b, x, y);
x -= (a / b) * y, swap(x, y);
return d;
}
int inv(int a) {
int x, y;
exgcd(a, P, x, y);
return (x % P + P) % P;
}

线性递推求乘法逆元

若需要频繁使用 [1,n] 内模 m 的逆元,其中 n<mm 为质数,可以考虑预处理 [1,n] 的所有逆元。枚举每个数字朴素求逆元是线性对数复杂度的,但事实上存在一种递推的求法,可以在线性复杂度内从 1 递推出 [1,n] 的所有逆元。

证明:

i=1 时,我们有 111(modm) ,因此 11=1

i>1 时,考虑 m=mii+mmodi=pi+r ,于是有

m0(modm)pi+r0(modm)pr1+i10(modm)i1pr1(modm)i1mi(mmodi)1(modm)

因此,我们可以从 1mmodi<i 的逆元推出 i 的逆元。

在这里我们使用 (mmi)(mmodi)1 防止出现负数。

时间复杂度 O(n)

空间复杂度 O(n)

const int P = 1e9 + 7;
const int N = 1e7 + 7;
int inv[N];
void get_inverse(int n) {
inv[1] = 1;
for (int i = 2;i <= n;i++) inv[i] = 1LL * (P - P / i) * inv[P % i] % P;
}

线性递推求阶乘逆元

通常在组合数学中需要频繁 i!,i[1,n]m 的逆元,其中 n<mm 为质数,我们同样也可以线性递推。我们可以线性求出 [1,n] 的逆元后再求阶乘的逆元,也可以从 (n!)1 倒推。我们采用倒推的方法。

证明:

已知 (n!)1 ,可以递推求出 n! 后,用费马小定理或exgcd求解 (n!)1

1i<n 时,有 (i!)1((i+1)!)1(i+1)(modm)

因此,我们可以从 (i+1)! 的逆元推出 i! 的逆元。

时间复杂度 O(n)

空间复杂度 O(n)

const int P = 1e9 + 7;
const int N = 1e7 + 7;
int qpow(int a, ll k) {
int ans = 1;
while (k) {
if (k & 1) ans = 1LL * ans * a % P;
k >>= 1;
a = 1LL * a * a % P;
}
return ans;
}
int fact[N], invfact[N];
void get_inverse(int n) {
fact[0] = 1;
for (int i = 1;i <= n;i++) fact[i] = 1LL * i * fact[i - 1] % P;
invfact[n] = qpow(fact[n], P - 2);
for (int i = n;i >= 1;i--) invfact[i - 1] = 1LL * invfact[i] * i % P;
}

一元一次同余方程

一元一次同余方程的定义与基本性质

定义 关于整数 x 的方程 axb(modm) ,其中 a,b 为整数, m 为正整数,称为一元一次同余方程。

约定 关于整数 x 的方程 axb(modm) ,我们认为在模 m 下同余的解 x 是同一个解。

解数的定义 方程不同的解的个数为方程的解数。

性质1 关于整数 x 的一元一次同余方程 axb(modm) ,等价于关于整数 x,y 的二元一次不定方程 ax+my=b ,其中 x 意义相同。因此,二元一次不定方程的性质与定理可以直接用于一元一次同余方程。

性质2 关于整数 x 的一元一次同余方程 axb(modm) ,其解数为 gcd(a,m)

性质2的证明:

通过性质1转换成二元一次不定方程,可求方程的所有解,容易发现解数为 gcd(a,m)

解一元一次同余方程

扩展欧几里得算法

关于整数 x 的同余方程 axb(modm) ,根据性质1,可以转化为关于整数 x,y 的不定方程 ax+my=b ,于是同前面所说的不定方程的解法一致。

时间复杂度 O(log(min{a,m}))

空间复杂度 O(1)

int exgcd(int a, int b, int &x, int &y) {
if (!b) { x = 1, y = 0; return a; }
int d = exgcd(b, a % b, x, y);
x -= (a / b) * y, swap(x, y);
return d;
}

一元一次同余方程组

一元一次同余方程组的定义与基本性质

定义 关于整数 x 的方程组

{a1xb1(modm1)a2xb2(modm2)akxbk(modmk)

其中 ai,bi(1ik) 为整数,mi(1ik) 为正整数,称为一元一次同余方程组。

约定 关于整数 x 的方程组 aixbi(modmi)(1ik) ,我们认为在模 M=lcm(m1,m2,,mk) 下同余的解 x 是同一个解。

解数的定义 方程组不同的解的个数为方程组的解数。

性质1 对于任意关于 x 的一元一次同余方程组

{a1xb1(modm1)a2xb2(modm2)akxbk(modmk)

等价于如下系数为 1 的方程组

{xa1,1(modm1)xa1,c1(modm1)xa2,1(modm2)xa2,c2(modm2)xak,1(modmk)xak,ck(modmk)

其中 ci(1ik) 为第 i 个方程 aixbi(modmi) 的解数, ai,j(1ik,1jci) 为第 i 个方程 aixbi(modmi) 的第 j 个解。

性质2 对于有如下形式的一元一次同余方程组

{xa1(modm1)xa2(modm2)xak(modmk)

其解 xM=lcm(m1,m2,,mk) 满足 gcd(ai,mi)=1(1ik)gcd(x,M)=1

性质1的证明:

对方程组中每个一元一次同余方程求解,可得对应方程的解集。显然,解集方程与原方程是同解的,可以等价替换原方程。

性质2的证明:

x 满足 xai(modmi)(1ik) , 根据同余基本性质10,有 gcd(x,mi)=gcd(ai,mi)

随后,结合 gcd 基本性质6,有 gcd(ai,mi)=gcd(x,mi)=1gcd(x,M)=1 ,因此得证。

中国剩余定理(孙子定理)

定理1(中国剩余定理) 对于有如下形式且满足 m1,m2,,mk 两两互质的一元一次同余方程组

{xa1(modm1)xa2(modm2)xak(modmk)

必有解,且解数为 1

定理1的证明:

M=lcm(m1,,mk)=ki=1miMi=MmiMi 在模 mi 下的必有逆元为 M1i

所以,我们可以构造出 x=ki=1aiMiM1i ,容易证明 x 是符合方程组的一个解。

同时,对于任意两个解 x1,x2 ,我们有 x1x2(modmi)(i=1,,k) ,根据同余基本性质9,可得 x1x2(modM) 。因此,解在模 M=lcm(m1,,mk)=ki=1mi 下是唯一的,即解数为 1

换句话说,如此方程在 [0,M) 中的必有解且唯一,即其最小正整数解 xmin

解一元一次同余方程组

中国剩余定理

对于一般的一元一次同余方程组,都可以化为有如下形式(即系数为 1 )的同余方程组

{xa1(modm1)xa2(modm2)xak(modmk)

若方程组还满足 m1,m2,,mk 两两互质,则可以用中国剩余定理(Chinese Remainder Theorem, CRT)证明中的构造法求解。

时间复杂度 O(klog(max{mi}))

空间复杂度 O(k)

ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) { x = 1, y = 0; return a; }
ll d = exgcd(b, a % b, x, y);
x -= (a / b) * y, swap(x, y);
return d;
}
ll inv(ll a, ll P) {
ll x, y;
exgcd(a, P, x, y);
return (x % P + P) % P;
}
ll CRT(const vector<ll> &a, const vector<ll> &p) {
int k = a.size() - 1;
ll P = 1, ans = 0;
for (int i = 1;i <= k;i++) P *= p[i];
for (int i = 1;i <= k;i++) {
ll Pi = P / p[i], invPi = inv(Pi, p[i]);
(ans += (__int128_t)a[i] * Pi * invPi % P) %= P;
}
return ans;
}

扩展中国剩余定理

若一般的一元一次同余方程组化为的同余方程组

{xa1(modm1)xa2(modm2)xak(modmk)

其模数 m1,m2,,mk 不满足两两互质,那么CRT是无法解决的。我们就需要使用扩展中国剩余定理(extended CRT,exCRT),虽说名字叫exCRT,但和CRT没有任何关系,单纯是CRT失效的时候用的一种新算法。

exCRT面对这种情况,采用的是朴素合并方程的方法。在对方程进行 k1 次合并后,得到最后一个方程,即方程组的解。

证明:

先考虑合并两个方程

{xa1(modm1)xa2(modm2)

根据一元一次同余方程基本性质1,我们可以将方程组改写为二元一次不定方程组

{x=m1p1+a1x=m2p2+a2

我们将两个方程相减可得 m1p1+m2(p2)=a2a1 ,根据裴蜀定理,当且仅当 gcd(m1,m2)a2a1 时,该方程有解。

在有解的情况,通过exgcd可求出 m1p1+m2(p2)=gcd(m1,m2) 的一组特解 p1,p2 ,根据裴蜀定理的定理 2 得原方程的所有解为

{P1=p1a2a1gcd(m1,m2)+km2gcd(m1,m2)P2=(p2)a2a1gcd(m1,m2)km1gcd(m1,m2)

其中 kZ

将通解 P1 代入 x=m1p1+a1 ,则有

x=a1+m1p1a2a1gcd(m1,m2)+km1m2gcd(m1,m2)=a1+m1p1a2a1gcd(m1,m2)+klcm(m1,m2)

其等价于同余方程 xa1+m1p1a2a1gcd(m1,m2)(modlcm(m1,m2)) ,于是我们就合并了两个方程。

对于原方程组

{xa1(modm1)xa2(modm2)xak(modmk)

只需要进行 k1 次合并即可。

在实现的过程中,原方程的特解 p1a2a1gcd(m1,m2) 可以模 m2gcd(m1,m2) (注意 a2a1 可能是负数,但不影响exgcd求解,只影响 % 运算的结果),可以避免一部分数字溢出。

时间复杂度 O(klog(max{mi}))

空间复杂度 O(k)

ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) { x = 1, y = 0; return a; }
ll d = exgcd(b, a % b, x, y);
x -= (a / b) * y, swap(x, y);
return d;
}
ll exCRT(const vector<ll> &a, const vector<ll> &p) {
int k = a.size() - 1;
ll ans = a[1], P = p[1];
for (int i = 2;i <= k;i++) {
ll x, y;
ll d = exgcd(P, p[i], x, y);
ll c = a[i] - ans;
if (c % d) return -1;
ll pd = p[i] / d;
x = ((__int128_t)c / d * x % pd + pd) % pd;
ans += P * x;
P *= pd;
ans %= P;
}
return ans;
}

特殊求和问题

问题描述

给定正整数 n 以及非负整数 a,b,c ,分别求

ni=0ai+bc,ni=0ai+bc2,ni=0iai+bc

求解方式

类欧几里得算法

暂时不学。

posted @   空白菌  阅读(501)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示