数论基础+裴蜀定理+线性同余方程+乘法逆元+中国剩余定理
本文内容大多搬运来自oi wiki!
数论基础
整除
整除的定义:设 \(a,b\in\mathbf{Z},a\ne 0\)。如果 \(\exists q\in\mathbf{Z}\),使得 b=aq,那么就说 b 可被 a 整除,记作 \(a\mid b\);b 不被 a 整除记作 \(a\nmid b\)。
同余
同余的定义:设整数 \(m\ne0\)。若 \(m\mid(a-b)\),称 m 为模数(模),a 同余于 b 模 m,b 是 a 对模 m 的剩余。记作 \(a\equiv b\pmod m\)。
否则,a 不同余于 b 模 m,b 不是 a 对模 m 的剩余。记作 \(a\not\equiv b\pmod m\)。
这样的等式,称为模 m 的同余式,简称同余式。
根据整除的性质,上述同余式也等价于 \(a\equiv b\pmod{(-m)}\)。
如果没有特别说明,模数总是正整数。
式中的 b 是 a 对模 m 的剩余,这个概念与余数完全一致。通过限定 b 的范围,相应的有 a 对模 m 的最小非负剩余、绝对最小剩余、最小正剩余。
裴蜀定理
设 a,b 是不全为零的整数,则存在整数 x,y, 使得 \(ax+by=\gcd(a,b)\)
进一步:
设自然数 a、b 和整数 n。a 与 b 互素(前提)。考察不定方程:ax+by=n,其中 x 和 y 为自然数。如果方程有解,称 n 可以被 a、b 表示。
记 C=ab-a-b。由 a 与 b 互素,C 必然为奇数。则有结论:对任意的整数 n,n 与 C-n 中有且仅有一个可以被表示。
即:可表示的数与不可表示的数在区间 [0,C] 对称(关于 C 的一半对称)。0 可被表示,C 不可被表示;负数不可被表示,大于 C 的数可被表示。
进一步的例题
相关资料
求不定方程
求\(ax+by=gcd(a,b)\)
已知a,b,求解\(ax+by=gcd(a,b)\)的一组整数解
利用扩展欧几里得算法求解,原理可见相关资料
int gcd(int a, int b){ if(b == 0) return a; else return gcd(b, a % b); }
int gcd(int a,int b){
if(b==0) return a;
else return gcd(b,a%b);
}
int exgcd(int a,int b,int &x,int &y){//返回gcd
if(b == 0) {x=1, y=0; return a;}
int x1, y1, d;
d = exgcd(b, a%b, x1, y1);
x = y1, y = x1-a/b*y1;
return d;
}
void exgcd(int a,int b,int &x,int &y){//不返回gcd
if(b==0){
x=1; y=0; return ;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
return ;
}
最终的\((x_0,y_0)\)即为特解,通解的构造利用 \(ax+by=0\) ,可得$x=x_0+\frac{b}{gcd(a,b)} * k ;y=y_0-\frac{a}{gcd(a,b)} * k $
求\(ax+by=c\)
已知a,b,c,求解\(ax+by=c\)的一组整数解
- 若 \(gcd(a,b) \mid c\),则先利用exgcd求得\(ax+by=gcd(a,b)\)的解,再乘以\(c / gcd(a,b)\),即得原方程的特解$(x_0,y_0) $
- 反之,即\(gcd(a,b) \nmid c\),则无整数解
相关资料
525 不定方程 扩展欧几里得算法原理
扩展欧几里得算法(简单易懂,详细分析)
线性同余方程
形如 \(ax\equiv b\pmod m\) 的方程称为 线性同余方程(Congruence Equation)。其中,a、b 和 m 为给定整数,x 为未知数。需要从区间 [0, n-1] 中求解 x,当解不唯一时需要求出全体解。
利用exgcd求解线性同余方程

代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int exgcd(int a,int b,int &x,int &y){
if(b == 0){x = 1, y = 0; return a;}
int x1, y1, d;
d = exgcd(b, a%b, x1, y1);
x = y1, y = x1-a/b*y1;
return d;
}
int main(){
int a, b, m, x, y;
scanf("%d%d%d", &a, &b, &m);
int d = exgcd(a, m, x, y);
if(b%d == 0)
printf("%d", 1ll*x*b/d%m);
else puts("none");
return 0;
}
相关资料
乘法逆元
求解数n在模 p 意义下的乘法逆元
当a与m互质时,对于方程\(ax\equiv 1\pmod m\),求a的乘法逆元x(0<x<m)
解法一: 费马小定理(当m为质数时)
数a的乘法逆元\(x=a^{m-2}\)
可利用快速幂方便求解
故,详见快速幂板子
解法二: 扩展欧几里得法(当\(gcd(a, m) = 1\)时)
- 先将乘法逆元形式转化为不定方程形式,变形等价\(ax+my=1\)
- 再利用exgcd求解\(ax+my=gcd(a,m)\)的解x,那么\((x\%m+m)\%m\)即为最终答案
exgcd板子:
void exgcd(int a, int b, int & x, int & y){
if(b == 0){
x = 1;
y = 0;
return;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
return;
}
cout << (p + x % p) % p << '\n';
线性求解 \(1,2,\dots,n\) 中每个数关于 p 的逆元
迭代实现
inv[1] = 1;
for(int i = 2; i <= n; ++ i){
inv[i] = (p - p / i) * inv[p % i] % p;
cout << inv[i] << '\n';
}
相关资料
取余题目集合
- https://atcoder.jp/contests/abc275/tasks/abc275_b 小坑勿怪!!!
代码——qiansui_code - https://loj.ac/p/110 模板题
代码——qiansui_code——扩展欧几里得法
代码——qiansui_code——费马小定理
3.有意思的一题:
https://atcoder.jp/contests/abc298/tasks/abc298_d
运用到取余+快速幂+思维
中国剩余定理 CRT
中国剩余定理 (Chinese Remainder Theorem, CRT) 可求解如下形式的一元线性同余方程组(其中 \(n_1\), \(n_2\), \(\cdots\), \(n_k\) 两两互质):
上面的「物不知数」问题就是一元线性同余方程组的一个实例。
求解过程:
- 计算所有模数的积 n;
- 对于第 i 个方程:
计算 \(m_i=\frac{n}{n_i}\)
计算 \(m_i\) 在模 \(n_i\) 意义下的 逆元 \(m_i^{-1}\)
计算 \(c_i=m_im_i^{-1}\)(不要对 \(n_i\) 取模) - 方程组在模 n 意义下的唯一解为:\(x=\sum_{i=1}^k a_ic_i \pmod n\)
板子:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll n, a[11], b[11];
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){x=1, y=0; return a;}
ll d, x1, y1;
d = exgcd(b, a%b, x1, y1);
x = y1, y = x1-a/b*y1;
return d;
}
ll CRT(ll m[], ll r[]){
ll M = 1, ans = 0;
for(int i=1;i<=n;i++) M*=m[i];
for(int i=1; i<=n; i++){
ll c = M/m[i], x, y;
exgcd(c, m[i], x, y);
ans = (ans+r[i]*c*x%M)%M;
}
return (ans%M + M)%M;
}
int main(){
scanf("%lld", &n);
for(int i = 1; i <= n; ++i)
scanf("%lld%lld", a+i, b+i);
printf("%lld\n", CRT(a,b));
return 0;
}
相关资料
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/16842829.html

浙公网安备 33010602011771号