数论基础知识点整理(基础篇)
这是我在ACM竞赛中学习数论时整理的一些基础的知识点,主要讨论整除、同余、最大公约数以及素数及其判定、快速幂、逆元,写的不太专业,有错误的地方还请多批评指正!
文章目录
- 整除
- 同余
- 最大公约数
- 扩展欧几里德例题
- 最小公倍数
- 素数及其判定
- 整除分块
- 快速幂
- 逆元
- O(n)计算阶乘的逆元
整除
- 定义: 整数a,b∈Z,且a≠0a, b\in\Z,且a\neq0a,b∈Z,且a=0,若∃q\exists q∃q,使得b=aqb=aqb=aq,则称b可被a整除(或a能整除b),记作a∣ba\mid ba∣b;且称b是a的倍数,a是b的约数(或因子、因数)。若a不能整除b,则记作a∤ba\nmid ba∤b
- 定理
- 1. a∣b,且b∣c,则a∣ca\mid b,且b\mid c, 则a\mid ca∣b,且b∣c,则a∣c
- 证明: ∵a∣b,且b∣c;令b=pa,c=qb,∴c=pqa\because a\mid b,且b\mid c;令b=pa,c=qb,\therefore c=pqa∵a∣b,且b∣c;令b=pa,c=qb,∴c=pqa,根据整除定义即a∣ca\mid ca∣c
- 2. a∣b,且a∣c,则∀x,y,满足a∣bx+cya\mid b,且a\mid c,则\forall x,y,满足a\mid bx+cya∣b,且a∣c,则∀x,y,满足a∣bx+cy
- 证明:∵a∣b且a∣c,令b=pa,c=qa,则bx+cy=pax+qay=(px+qy)a,∴a∣bx+cy\because a\mid b且a\mid c,令b=pa,c=qa,则bx+cy=pax+qay=(px+qy)a,\therefore a\mid bx+cy∵a∣b且a∣c,令b=pa,c=qa,则bx+cy=pax+qay=(px+qy)a,∴a∣bx+cy
- 3. 若a≠0,b=aq+ca\neq0,b=aq+ca=0,b=aq+c,那么a∣ba\mid ba∣b 的充分必要条件是a∣ca\mid ca∣c
- 充分性证明:∵a∣b,令b=pa,则c=(p−q)a,∴a∣c\because a\mid b,令b=pa,则c=(p-q)a,\therefore a\mid c∵a∣b,令b=pa,则c=(p−q)a,∴a∣c
- 必要性证明: ∵a∣c,令c=pa,则b=(p+q)a,∴a∣b\because a\mid c,令c=pa,则b=(p+q)a,\therefore a\mid b∵a∣c,令c=pa,则b=(p+q)a,∴a∣b
- 1. a∣b,且b∣c,则a∣ca\mid b,且b\mid c, 则a\mid ca∣b,且b∣c,则a∣c
同余
∀a,b∈Z,且a≠0,∃p,c\forall a,b\in\Z,且a\neq 0,\exists p,c∀a,b∈Z,且a=0,∃p,c,使得等式b=pa+c,0⩽c⩽a−1b=pa+c,0\leqslant c\leqslant a-1b=pa+c,0⩽c⩽a−1成立
- 取模运算
b对a取模的结果即b除以a的余数,符号表示为 bmodab\mod abmoda,计算值为b−⌊ba⌋∗ab-\lfloor \frac{b}{a}\rfloor*ab−⌊ab⌋∗a。 - 同余
m⩾1,a,b∈Z,若m∣(a−b)m\geqslant 1,a,b\in\Z,若m\mid(a-b)m⩾1,a,b∈Z,若m∣(a−b),则称a与b关于模m同余,符号表示为a≡b(modm)a\equiv b(mod\ m)a≡b(mod m)。 - 性质
- 1. 自反性: a≡a(modm)a\equiv a(mod\ m)a≡a(mod m)
- 2. 对称性: a≡b(modm)则b≡a(modm)a\equiv b(mod\ m)则b\equiv a(mod\ m)a≡b(mod m)则b≡a(mod m)
- 3. 传递性:a≡b(modm)且b≡c(modm)则a≡c(modm)a\equiv b(mod\ m)且b\equiv c(mod\ m)则a\equiv c(mod\ m)a≡b(mod m)且b≡c(mod m)则a≡c(mod m)
- 证明:∵a≡b(modm)且b≡c(modm)\because a\equiv b(mod\ m)且b\equiv c(mod\ m)∵a≡b(mod m)且b≡c(mod m)则根据同余定义m∣(a−b),m∣(b−c)m\mid (a-b),m\mid(b-c)m∣(a−b),m∣(b−c),再根据整除的定理2,m∣[(a−b)+(b−c)],即m∣(a−c)m\mid[(a-b)+(b-c)],即m\mid(a-c)m∣[(a−b)+(b−c)],即m∣(a−c),再由同余定义得a≡c(modm)a\equiv c(mod\ m)a≡c(mod m)
- 4. 同余式相加:a≡b(modm)且c≡d(modm)则a±c≡b±d(modm)a\equiv b(mod\ m)且c\equiv d(mod\ m)则a\pm c\equiv b\pm d(mod\ m)a≡b(mod m)且c≡d(mod m)则a±c≡b±d(mod m)
- 证明:∵a≡b(modm)且c≡d(modm)∴m∣(a−b),m∣(c−d)∴m∣[(a−b)+(c−d)],m∣[(a+c)−(b+d)]∴a+c≡b+d(modm)\because a\equiv b(mod\ m)且c\equiv d(mod\ m)\therefore m\mid(a-b),m\mid(c-d)\therefore m\mid[(a-b)+(c-d)],m\mid[(a+c)-(b+d)]\therefore a+c\equiv b+d(mod\ m)∵a≡b(mod m)且c≡d(mod m)∴m∣(a−b),m∣(c−d)∴m∣[(a−b)+(c−d)],m∣[(a+c)−(b+d)]∴a+c≡b+d(mod m)同理也能证明a−c≡b−d(modm)a-c\equiv b- d(mod\ m)a−c≡b−d(mod m)
- 5. 同余式相乘:a≡b(modm)且c≡d(modm)则ac≡bd(modm)a\equiv b(mod\ m)且c\equiv d(mod\ m)则ac\equiv bd(mod\ m)a≡b(mod m)且c≡d(mod m)则ac≡bd(mod m)
- 证明:∵a≡b(modm)且c≡d(modm)∴m∣(a−b),m∣(c−d)∴m∣[(a−b)c+(c−d)b]∴m∣(ac−bd)∴ac≡bd(modm)\because a\equiv b(mod\ m)且c\equiv d(mod\ m)\therefore m\mid(a-b),m\mid(c-d)\therefore m\mid[(a-b)c+(c-d)b]\therefore m\mid(ac-bd) \therefore ac\equiv bd(mod\ m)∵a≡b(mod m)且c≡d(mod m)∴m∣(a−b),m∣(c−d)∴m∣[(a−b)c+(c−d)b]∴m∣(ac−bd)∴ac≡bd(mod m)
- 6. 除法: ac≡bc(modm)则a≡b(modmgcd(c,m))ac\equiv bc(mod\ m)则a\equiv b(mod \ \frac{m}{gcd(c, m)})ac≡bc(mod m)则a≡b(mod gcd(c,m)m),gcd(c,m)gcd(c, m)gcd(c,m)就是c和m的最大公约数
- 证明: 令d=gcd(c,m)d=gcd(c,m)d=gcd(c,m),则令c=pd,m=qdc=pd,m=qdc=pd,m=qd,满足gcd(p,q)=1gcd(p,q)=1gcd(p,q)=1∵ac≡bc(modm)⇒qd∣(a−b)pd⇒q∣(a−b)p∵gcd(p,q)=1∴q∣(a−b)∴a≡b(modq)\because ac\equiv bc(mod\ m)\Rightarrow qd\mid(a-b)pd\Rightarrow q\mid(a-b)p\because gcd(p, q)=1\therefore q\mid(a-b)\therefore a\equiv b(mod\ q)∵ac≡bc(mod m)⇒qd∣(a−b)pd⇒q∣(a−b)p∵gcd(p,q)=1∴q∣(a−b)∴a≡b(mod q),q即mgcd(c,m)\frac{m}{gcd(c, m)}gcd(c,m)m
- 7. 幂运算: a≡b(modm)则an≡bn(modm)a\equiv b(mod\ m)则a^{n}\equiv b^{n}(mod\ m)a≡b(mod m)则an≡bn(mod m)
最大公约数
最大公约数(Greatest Common Divisor,简称GCD)
定义: a,b的公共的约数中最大的约数,记作gcd(a,b)gcd(a,b)gcd(a,b), gcd(a,b)=max{d,d∣a且d∣b}gcd(a,b)=max \{ d, d\mid a且d\mid b\}gcd(a,b)=max{d,d∣a且d∣b}
性质:
- 1. gcd(a,b)=gcd(b,a)gcd(a,b)=gcd(b,a)gcd(a,b)=gcd(b,a)
- 2. gcd(a,b)=gcd(a,a±b)gcd(a,b)=gcd(a,a\pm b)gcd(a,b)=gcd(a,a±b)
- 证明:请点击链接
- 3. gcd(a,b)=gcd(a±mb)gcd(a,b)=gcd(a\pm mb)gcd(a,b)=gcd(a±mb)
- 4. gcd(a,b)=gcd(b,a%b)gcd(a,b)=gcd(b,a\%b)gcd(a,b)=gcd(b,a%b)
- 证明: gcd(b,a%b)=gcd(b,a−⌊ab⌋∗b)gcd(b,a\%b)=gcd(b,a-\lfloor\frac{a}{b}\rfloor*b)gcd(b,a%b)=gcd(b,a−⌊ba⌋∗b),根据性质1、3可得gcd(a,b)=gcd(b,a%b)
- 5.gcd(ma,mb)=m∗gcd(a,b)gcd(ma,mb)=m*gcd(a,b)gcd(ma,mb)=m∗gcd(a,b)
- 证明: 令d=gcd(a,b),则d∣a,d∣b,满足a=pd,b=qd且gcd(p,q)=1∴gcd(ma,mb)=gcd(mdp,mdq)=mdd=gcd(a,b),则d|a,d|b,满足a=pd,b=qd且gcd(p,q)=1\therefore gcd(ma,mb)=gcd(mdp,mdq)=mdd=gcd(a,b),则d∣a,d∣b,满足a=pd,b=qd且gcd(p,q)=1∴gcd(ma,mb)=gcd(mdp,mdq)=md
求解方法
辗转相除法(欧几里德法)- 原理:
gcd(a,b)=gcd(b,a%b)gcd(a,b)=gcd(b,a\%b)gcd(a,b)=gcd(b,a%b)
当b=0时,gcd(a,b)=a,否则根据公式继续迭代。 - 代码实现:
int gcd(int a, int b){return b == 0 ? a : gcd(b, a%b); }
- 原理:
扩展欧几里德:ax+by=gcd(a,b)
- 原理:
令d=gcd(a,b)令d=gcd(a,b)令d=gcd(a,b)
∵ax+by=gcd(a,b)\because ax+by=gcd(a,b)∵ax+by=gcd(a,b)
∴bx′+(a%b)y′=gcd(b,a%b)\therefore bx^{'} +(a\%b)y^{'}=gcd(b,a\%b)∴bx′+(a%b)y′=gcd(b,a%b)
∴bx′+(a%b)y′=ax+by\therefore bx^{'}+(a\%b)y^{'}=ax+by∴bx′+(a%b)y′=ax+by
∴ay′+b(x′−⌊ab⌋∗y′)=ax+by\therefore ay^{'}+b(x^{'}-\lfloor\frac{a}{b}\rfloor*y^{'})=ax+by∴ay′+b(x′−⌊ba⌋∗y′)=ax+by要使任意a,b都满足此等式,
则x=y′,y=x′−⌊ab⌋∗y′x=y^{'},y=x^{'}-\lfloor\frac{a}{b}\rfloor*y^{'}x=y′,y=x′−⌊ba⌋∗y′
当b=0时,ax=a,则x=1,y=0;
否则,令用gcd(a,b)=gcd(b,a%b)gcd(a,b)=gcd(b,a\%b)gcd(a,b)=gcd(b,a%b)递归求解,回溯时利用两式之间的关系,更新x,y,可求得方程的一组整数解。 - 代码实现:
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);int z = x; x = y; y = z - (a / b) * y;return d; }
- 方程ax+bx=cax+bx=cax+bx=c:
利用扩展欧几里德算法可求得ax+by=gcd(a,b)ax+by=gcd(a,b)ax+by=gcd(a,b)的一组解x0,y0x_0,y_0x0,y0;令d=gcd(a,b)
+ 当d∣cd\mid cd∣c时,方程有解,其一组解为:
x=x0∗cd,y=y0∗cdx=x_0*\frac{c}{d},y=y_0*\frac{c}{d}x=x0∗dc,y=y0∗dc
通解为:
x=x0∗cd+k∗bdx=x_0*\frac{c}{d}+k*\frac{b}{d}x=x0∗dc+k∗db
y=y0∗cd+k∗ad,(k∈Z)y=y_0*\frac{c}{d}+k*\frac{a}{d},(k\in\Z)y=y0∗dc+k∗da,(k∈Z)。
- 原理:
扩展欧几里德例题
- POJ1061
- 题意: 两只青蛙在同一条维度线上朝西跳动, 青蛙A起始点坐标x,每次跳动m米,青蛙B起始点坐标y,每次跳动n米,问他们跳动多少次能沟相遇,不能输出Impossible
- 题解: 设两只青蛙跳动次数为t,则此时青蛙A的坐标为(x+mt)%l,青蛙B的坐标为(y+nt)%l,当两只青蛙相遇时,满足
(x+mt)≡(y+nt)(modl)(x+mt)\equiv(y+nt)(\mod l)(x+mt)≡(y+nt)(modl)
l∣((x+mt)−(y+nt))l\mid((x+mt)-(y+nt))l∣((x+mt)−(y+nt))
∃k∈Z\exists k\in\Z∃k∈Z使得等式((x+mt)−(y+nt))=kl((x+mt)-(y+nt))=kl((x+mt)−(y+nt))=kl成立
(m−n)t+lk=x−y(m-n)t+lk=x-y(m−n)t+lk=x−y
当gcd(m−n,l)∣(x−y)gcd(m-n,l)\mid(x-y)gcd(m−n,l)∣(x−y)时,方程有解,即答案就是t的最小正整数解,否则方程无解,则两青蛙永远不能相遇。 - 代码实现:
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; #define mes(a, val) memset(a, val, sizeof a) #define mec(b, a) memcpy(b, a, sizeof a) #define ll long longll 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);ll z = x; x = y; y = z - (a / b) * y;return d; } int main() {ll n, m, x, y, l;scanf("%lld %lld %lld %lld %lld", &x, &y, &m, &n, &l);ll a = n - m;ll b = l;ll c = x - y;ll d = exgcd(a, b, x, y);if(d < 0) d = -d;if(c % d){printf("Impossible\n");}else {ll p = b / d;x = x * c / d;x = ((x % p) + p) % p;printf("%lld\n", x);}return 0; }
最小公倍数
最小公倍数(Least Common Multiple 简称LCM )
- 定义: a, b的所有公共的倍数中最小的公倍数,记作lcm(a,b), lcm(a,b)=min{d,a∣d且b∣d}lcm(a,b)=min\{d,a\mid d且b\mid d\}lcm(a,b)=min{d,a∣d且b∣d}。
- 计算方法: 公式lcm(a,b)=a∗bgcd(a,b)lcm(a,b)=\frac{a*b}{gcd(a,b)}lcm(a,b)=gcd(a,b)a∗b
素数及其判定
- 素数(也称质数): 一个正整数n是素数当且仅当只能被1和其自身整除,否则就称n是合数 。
注: 1既不是素数也不是合数,最小的素数是2 - 素数判定
- 1. 暴力枚举:
- 原理: 循环遍历i从2到n\sqrt{n}n,只要存在 n%i=0n\%i=0n%i=0即可判定n不是素数,这样每次判定时间复杂度都是O(n)O(\sqrt{n})O(n)
- 代码实现
bool isprime(int n){for(int i = 2; i * i <= n; i ++){if(n % i == 0) return false; }return true; }
- 2. 埃拉托斯特尼筛法,简称埃氏筛:
是一种用来求自然数n以内的全部素数的方法 。- 原理: 一个合数必然可以表示一个质数和另一个数相乘。对于一个素数p,那么p的倍数2p,3p,…kp,…必然都是合数。时间复杂度为O(nlog(n))O(nlog(n))O(nlog(n))
- 实现代码:
/*定义数组:isprime[i],表示数组i是否时素数*/ const int maxn = 1e5 + 100; int m; bool isprime[maxn]; int p[maxn]; void sieze(int n) {m = 0; memset(isprime, true, sizeof(isprime));for(int i = 2; i <= n; i ++){if(isprime[i]){///表明 i 就是素数p[++ m] = i;for(int j = 2 * i; j <= n; j += i){isprime[j] = false;}}} }
- 不足: 仔细分析可以看出,这种方法筛出n以内的所有素数还是有不足之处的。原因在于每个合数会被其每一个质因子筛到一次。因此就有了接下来的线性筛。
- 3. 线性筛
它能在O(n)O(n)O(n)的时间复杂度内筛选出n以内的所有素数。- 原理:
线性筛能保证n以内的任何一个数只能被他的最小质因子筛一次。
一个数n可以表示成n=Factorymax∗pn=Factory_{max}*pn=Factorymax∗p
FactorymaxFactory_{max}Factorymax是除n以外的最大因子,p是n的质因子,满足p小于等于 FactorymaxFactory_{max}Factorymax 的所有质因子。
用数组v[i]表示i是否是素数,v[i]为false时表示i是素数,
然后便利之前筛出的所有素数,v[i*p[j]]则不是素数,标记为true。 i % p[j] 为0时,跳出第二层循环,以此保证每个数只被他的最小质因子筛一次。
当i %p[j]为0时,p[j]已经是i的最小值质因子,且p[j]时i*p[j]的最小值质因子,p[j+1]大于i的最小质因子,也就不是i*p[j]的最小质因子。 - 代码实现:
const int maxn = 1e5 + 100; int m; bool v[maxn]; int p[maxn]; void sieze(int n) {m = 0; memset(v, false, sizeof v);for(int i = 2; i <= n; i ++){if(!v[i]) {p[++ m] = i;}for(int j = 1; j <= m && i * p[j] <= n; j ++){v[i * p[j]] = true;if(i % p[j] == 0) break;//这条语句很关键}} }
- 原理:
- 1. 暴力枚举:
整除分块
计算表达式:∑i=1n⌊ni⌋\sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloor∑i=1n⌊in⌋
- 1.暴力O(n)求解不多赘述。
- 2.OnO\sqrt{n}On优美解法
- 证明请看,这位大佬的证明非常清晰,很容易理解。
- 代码实现
int solve(int n) {int ans = 0;for(int l = 1, r; l <= n; l = r + 1){r = n / (n / l);ans += (r - l + 1) * (n / l);}return ans; }
- 例题Gym100923I
- 题意: 有n个男的,n个女的,第i个人都有为当前一个大小为i的懒惰值,当一男一女懒惰值的乘积<=n他们就就可以一起跳舞,请问有多少种组合可能;
- 题解: 从1~n枚举男生的懒惰值i,满足条件的女女生个数就是⌊ni⌋\lfloor\frac{n}{i}\rfloor⌊in⌋,ans=∑i=1n⌊ni⌋ans=\sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloorans=∑i=1n⌊in⌋,经典的整除分块例题。
- 代码实现:
#include <bits/stdc++.h> using namespace std; #define mes(a, val) memset(a, val, sizeof a) #define mec(b, a) memcpy(b, a, sizeof a) #define ll long longll solve(ll n) {ll ans = 0;for(ll l = 1, r; l <= n; l = r + 1){r = n / (n / l);ans += (r - l + 1) * (n / l);}return ans; } int main() { freopen("perechi3.in", "r", stdin);freopen("perechi3.out", "w", stdout);int T; scanf("%d", &T);while(T --){ll n; scanf("%lld", &n);ll ans = solve(n);printf("%lld\n", ans);}return 0; }
快速幂
51Nod快速幂
- 问题描述: 计算ana^{n}an为例
- 问题分析: 显然O(n)O(n)O(n)暴力是不能解决问题的,下面我们介绍一种算法 (快速幂) ,它能在O(logn)O(log n)O(logn)时间复杂度内解决此问题。
- 快速幂原理:
将正整数n二进制拆分成n=bn−1bn−2...b0,bi∈{0,1}n=b_{n-1}b_{n-2}...b_{0},b_{i}\in\{0,1\}n=bn−1bn−2...b0,bi∈{0,1}
即n=2n−1bn−1+2n−2bn−2+...+20b0n=2^{n-1}b_{n-1}+2^{n-2}b_{n-2}+...+2^{0}b_{0}n=2n−1bn−1+2n−2bn−2+...+20b0
∴an=a2n−1bn−1+2n−2bn−2+...+20b0\therefore a^{n}=a^{2^{n-1}b_{n-1}+2^{n-2}b_{n-2}+...+2^{0}b_{0}}∴an=a2n−1bn−1+2n−2bn−2+...+20b0
=a2n−1bn−1∗a2n−2bn−2∗...∗a20b0\quad\quad=a^{2^{n-1}b_{n-1}}*a^{2^{n-2}b_{n-2}}*...*a^{2^{0}b_{0}}=a2n−1bn−1∗a2n−2bn−2∗...∗a20b0
因此我们可以设置一个res(初始为1)和一个base(初始值为a),也即a^{0},在对n进行二进制拆分过程中,当第i位(从右往左第i位)为1时,则将res乘上base,并且base每次都乘上自己。其实在整个过程中,basei=a2ibase_{i}=a^{2^{i}}basei=a2i。时间复杂度O(log(n))O(log(n))O(log(n))int ksm(int a, int n, int mod) {int res = 1;while(n){if(n & 1) res = res * a % mod; //二进制拆分n第i位(从右往左)为1a = a * a % mod;n >>= 1;}return res; }
逆元
例题hdu1576
- 定义: 整数a,b,若a∗b≡1(modp)a*b\equiv1(\mod p)a∗b≡1(modp),那么则称a和b互为模p意义下的逆元。
- 注:逆元需要在取模下才有意义,a对模p意义下的逆元即a在模p意义下的倒数
- 逆元的意义: 如何求解 ab%p\frac{a}{b}\% pba%p(p是质数)?
整数的除法运算是向下取整,若b不能整除a,进行除法运算后在对p取模,多得到的并是正确结果,这一点应该很好理解。
逆元的作用就在如此,他能将除以一个数等价于乘上这个的逆元。
ab≡a∗1b(modp)\frac{a}{b}\equiv a*\frac{1}{b}(\mod p)ba≡a∗b1(modp)
设b在模p意义下的逆元为invb,则
invb∗b≡1(modp)⇔invb≡1b(modp)invb*b\equiv1(\mod p)\Leftrightarrow invb\equiv\frac{1}{b}(\mod p)invb∗b≡1(modp)⇔invb≡b1(modp)
∴ab≡a∗invb(modp)\therefore \frac{a}{b}\equiv a*invb(\mod p)∴ba≡a∗invb(modp) - 逆元求解方法
- 1.费马小定理
- 满足条件: 模数p必须是素数。
- 原理: ap−1≡1(modp)a^{p-1}\equiv1(\mod p)ap−1≡1(modp),p是素数 (再此不做证明)
因此a∗ap−2≡1(modp)a*a^{p-2}\equiv1(\mod p)a∗ap−2≡1(modp)
即ap−2a^{p-2}ap−2就是a在模p意义下的逆元,inva=ap−2inva=a^{p-2}inva=ap−2,利用快速幂可以求解
- 2.扩展欧几里德
- 满足条件: gcd(a,p)=1gcd(a,p)=1gcd(a,p)=1即a与p互质。
- 原理: inva∗a≡1(modp)inva *a\equiv1(\mod p)inva∗a≡1(modp)
∴p∣(inva∗a−1)\therefore p\mid(inva*a-1)∴p∣(inva∗a−1)
∴∃k∈Z,inva∗a−1=pk\therefore \exists k\in\Z,inva*a-1=pk∴∃k∈Z,inva∗a−1=pk
∴inva∗a+k∗p=1,∵gcd(a,p)=1\therefore inva*a+k*p=1,\because gcd(a,p)=1∴inva∗a+k∗p=1,∵gcd(a,p)=1
因此次方程一定有解,利用扩展欧几里德算法可求得inva
- 递推公式
- 满足条件: 模数p必定是素数 。
- 原理:
p=p%a+⌊pa⌋∗ap=p\%a+\lfloor\frac{p}{a}\rfloor*ap=p%a+⌊ap⌋∗a
令 x=p%a,y=⌊pa⌋x=p\%a,y=\lfloor\frac{p}{a}\rfloorx=p%a,y=⌊ap⌋
p%p=(x+y∗a)%pp\%p=(x+y*a)\%pp%p=(x+y∗a)%p
a−1%p=(p−x)∗y−1%pa^{-1}\%p=(p-x)*y^{-1}\%pa−1%p=(p−x)∗y−1%p
因此得 a−1=(p−⌊pa⌋)∗(p%a)−1%pa^{-1}=(p- \lfloor\frac{p}{a}\rfloor)*(p\% a)^{-1}\%pa−1=(p−⌊ap⌋)∗(p%a)−1%p
由此递推式可O(n)求解1~n所有数模p的逆元。 - 代码实现:
int inv[mod+5]; void getInv(int p) {inv[1] = 1;for(int i = 2; i < p; i ++){inv[i] = (p - p / i) * inv[p % i] % p;} }
- 1.费马小定理
O(n)计算阶乘的逆元
- 原理:
令f(n)=n!f(n)=n!f(n)=n!
f(n)=f(n−1)∗nf(n)=f(n-1)*nf(n)=f(n−1)∗n
f(n−1)−1=f(n)−1∗nf(n-1)^{-1}=f(n)^{-1}*nf(n−1)−1=f(n)−1∗n
先O(n)O(n)O(n) 预处理出 1~n 的阶乘,计算出 f(n)−1f(n)^{-1}f(n)−1 则可通过递推公式往下求解 1~n-1 以内所有阶乘的逆元。 - 代码实现:
const int maxn = 1e5 + 10; int f[maxn], invf[maxn]; int p; int ksm(int a, int n, int p) {int res = 1;while(n){if(n & 1) res = 1ll * res * a % p;a = 1ll * a * a % p;n >>= 1;}return res; } void init(int n) {f[0] = 1; f[1] = 1;for(int i = 2; i <= n; i ++){f[i] = 1ll * f[i-1] * i % p;}invf[n] = ksm(f[n], p - 2, p);for(int i = n - 1; i >= 0; i --){invf[i] = 1ll * invf[i+1] * (i + 1) % p;} }
- 例题
51Nod1118- 题意:
M * N的方格,一个机器人从左上走到右下,只能向右或向下走。有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。 - 题解: 答案就是Cn+mnC_{n+m}^{n}Cn+mn
- 代码实现:
import java.math.*; import java.util.*;public class Main {public static long mod = 1000000007;public static long f[] = new long[2100];public static long invf[] = new long[2100];public static long ksm(long a, long n, long p) {long res = 1;while(n > 0) {if(n % 2 == 1) res = res * a % p;a = a * a % p;n >>= 1;}return res;}//计算阶乘的逆元public static void init(int n) {f[0] = 1;for(int i = 1; i <= n; i ++) {f[i] = f[i-1] * i % mod;}invf[n] = ksm(f[n], mod-2, mod);for(int i = n - 1; i >= 0; i --) {invf[i] = invf[i+1] * (i + 1) % mod;}}public static long get(int n, int m) {n --; m --;long res = f[n+m]*invf[n]%mod*invf[m]%mod;res = res % mod;return res;}public static void main(String[] args) {Scanner cin = new Scanner(System.in);init(2005);int n = cin.nextInt(); int m = cin.nextInt();System.out.println(get(n, m));} }
- 题意:
数论基础知识点整理(基础篇)相关推荐
- python基础知识整理-python爬虫基础知识点整理
首先爬虫是什么? 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本. 根据我的经验,要学习Python爬虫 ...
- python基础知识500题_python爬虫基础知识点整理
更多编程教程请到:菜鸟教程 https://www.piaodoo.com/ 友情链接: 高州阳光论坛https://www.hnthzk.com/ 人人影视http://www.sfkyty.com ...
- Java基础知识点整理(2022年最新版)
看了网上很多关于Java基础知识点整理的文章,但是感觉都不是很好,要么不全面,要么不准确,要么排版太乱了,所以今天整理了一份Java基础知识点整理(2022年最新版),希望对大家有帮助哈~ 由于本文篇 ...
- python爬虫基础知识点整理
更多编程教程请到:菜鸟教程 https://www.piaodoo.com/ 友情链接: 高州阳光论坛https://www.hnthzk.com/ 人人影视http://www.sfkyty.com ...
- mysql 存储引擎 面试_搞定PHP面试 - MySQL基础知识点整理 - 存储引擎
MySQL基础知识点整理 - 存储引擎 0. 查看 MySQL 支持的存储引擎 可以在 mysql 客户端中,使用 show engines; 命令可以查看MySQL支持的引擎: mysql> ...
- java重要基础知识点_java基础知识点整理
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 java基础知识点整理1.&和&&的区别? &:逻辑与(and),运算符两边的表达式均为true时,整个结果才为true. ...
- 百度 java基础_java基础知识点整理
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 java基础知识点整理1.&和&&的区别? &:逻辑与(and),运算符两边的表达式均为true时,整个结果才为true. ...
- java基础知识点整理一
java基础知识点整理一 引言 '''突然发觉任何一门语言的基础知识部分,都比较杂一些.如果个人经过梳理之后,知识体系系统化,可以让基础更加牢靠一些.但是还是会有一些遗忘.所以,我想把一些比较重要但是 ...
- 计算机二级基础知识点全部讲解,计算机二级基础知识点整理
计算机二级基础知识点整理 第一章 数据结构与算法 算法---是一组严谨地定义运算顺序的规则 算法的基本要素---一是对数据对象的运算和操作,二是算法的控制结构 算法设计基本方法---列举法.归纳法.递 ...
- MySQL基础知识点整理 - 存储引擎
MySQL基础知识点整理 - 存储引擎 0. 查看 MySQL 支持的存储引擎 可以在 mysql 客户端中,使用 show engines; 命令可以查看MySQL支持的引擎: mysql> ...
最新文章
- OpenCV Mat矩阵(图像Mat)初始化及访问方法
- Android中给listview/gridview设置动画(逐条加载条目动画)
- Ubuntu解决gedit warning问题的方法
- 牛客题霸 SQL2 查找入职员工时间排名倒数第三的员工所有信息
- CMOS与BIOS的区别
- 冬季小学期 NIIT公司 web前端培训 CSS
- 监听APP升级广播处理
- Ubuntu系统设置截图快捷键
- 在家快发霉了?数据告诉你,网友们都怎么打发时间
- DTL语言学习(四){% spaceless %}、{% autospace %}和{% verbatim %}标签
- POJ1061青蛙的约会(拓展欧几里得)
- win10创意者更新是什么 Win10创意者更新升级方法
- 嵌入式系统之-小米路由器3G v1
- 线性探测法和平方探测法 - 哈希表 - 完整代码
- 分布式项目-谷粒商城。
- js网状特效源代码下载
- GCN-LSTM预测道路交通车辆速度 英文 Vehicle Speed Forecasting Based On GCN-LSTM Combined Model
- 【总结】手机图片预览插件photoswipe使用总结
- 13. Redis底层实现 List
- linux cgi 更改网络配置,惨绝人寰的蓝点linux2.0配置perl cgi-CGI教程,CGI文档
热门文章
- 单元测试用例编写总结
- Vijos训练计划 1-1 计数问题
- 打开cad图纸计算机打不开,cad打不开_CAD图纸打开未响应怎么解决
- 语音计算机怎么切换音乐模式,怎么实现一个设备播放一个程序的声音呢?
- win7查看计算机硬盘序列号,win7系统通过cmd查看硬盘序列号的操作方法
- 基于springboot+vue的毕业论文选题答辩管理系统
- jade的基本使用方法
- Flutter安装依赖包
- 和秋叶一起学PPT之四步走(课时二)
- 200套IT电子类数码产品行业响应式html5模板电器销售企业网站模板服装服饰购物电商网站模板鞋子电子商务html网站模板html5网页静态模板Bootstrap扁平化网站源码css3手机seo自适响