同余定理
同余定理是数论中的重要概念。给定一个正整数m,如果两个整数a和b满足(a-b)能够被m整除,即(a-b)/m得到一个整数,那么就称整数a与b对模m同余,记作a≡b(mod m)
。
两个整数a、b,若它们除以整数m所得的余数相等,则称a与b对模m同余或a同余于b模m
同余性质
- 反身性:a≡a (mod m)
- 对称性: 若a≡b(mod m),则b≡a(mod m)
- 传递性: 若a≡b(mod m),b≡c(mod m),则a≡c(mod m)
- 同余式相加:若a≡b(mod m),b≡c(mod m),则a ± c≡b ± d(mod m)
- 同余式相乘:若a≡b(mod m),b≡c(mod m),则ac≡bd(mod m)
- 线性运算:如果a≡b(mod m),c≡d(mod m),那么a ± c≡b ± d(mod m),且
a * c≡b * d(mod m)
- 除法:若ac ≡ bc (mod m) c≠0 则 a≡ b (mod m/gcd(c,m)) 其中gcd(c,m)表示c,m的最大公约数。特殊地 ,gcd(c,m)=1 则a ≡ b (mod m)
- 幂运算:如果a ≡ b (mod m),那么a^n ≡ b^n (mod m)
- 若a ≡ b (mod m),n|m,则 a ≡ b (mod n)
- 若a ≡ b (mod mi) (i=1,2…n) 则 a ≡ b (mod [m1,m2,…mn]) 其中[m1,m2,…mn]表示m1,m2,…mn的最小公倍数
相关定理
- 欧拉定理
- 费马小定理
- 中国剩余定理(孙子定理)
逆元
( a / b ) % p = ( a ∗ b 的 逆 元 ) % p (a/b) \% p = (a * b的逆元) \% p (a/b)%p=(a∗b的逆元)%p
费马小定理求逆元:
b的逆元 = b p − 2 b^{p-2} bp−2
线性递推
#include<bits/stdc++.h>
#define N 3000010
typedef long long ll;
using namespace std;
int inv[N],n,p;
inline int read() {
int f=1,x=0;
char ch;
do {
ch=getchar();
if(ch=='-')f=-1;
} while(ch<'0'||ch>'9');
do {
x=x*10+ch-'0';
ch=getchar();
} while(ch>='0'&&ch<='9');
return f*x;
}
int main() {
n=read();
p=read();
inv[1]=1;
puts("1");
for(int i= 2; i <= n; i++) {
inv[i] = (ll)(p - p / i) * inv[p % i] % p;
printf("%d\n", inv[i]);
}
}
中国剩余定理
在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。具体解法分三步:
- 找出三个数:从3和5的公倍数中找出被7除余1的最小数15,从3和7的公倍数中找出被5除余1 的最小数21,最后从5和7的公倍数中找出除3余1的最小数70。
- 用15乘以2(2为最终结果除以7的余数),用21乘以3(3为最终结果除以5的余数),同理,用70乘以2(2为最终结果除以3的余数),然后把三个乘积相加15∗2+21∗3+70∗2得到和233。
- 用233除以3,5,7三个数的最小公倍数105,得到余数23,即233%105=23,这个余数23就是符合条件的最小数。
就这么简单。我们在感叹神奇的同时不禁想知道古人是如何想到这个方法的,有什么基本的数学依据吗?
拓展
求解同余方程组
/*
https://www.luogu.com.cn/problem/P4777
*/
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
lt read()
{
lt f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=100010;
int n;
lt ai[maxn],bi[maxn];
lt mul(lt a,lt b,lt mod) // 龟速乘
{
lt res=0;
while(b>0)
{
if(b&1) res=(res+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return res;
}
lt exgcd(lt a,lt b,lt &x,lt &y)
{
if(b==0){x=1;y=0;return a;}
lt gcd=exgcd(b,a%b,x,y);
lt tp=x;
x=y; y=tp-a/b*y;
return gcd;
}
lt excrt()
{
lt x,y,k;
lt M=bi[1],ans=ai[1];//第一个方程的解特判 ans 为前k - 1 个方程组的通解
for(int i=2;i<=n;i++)
{
lt a=M,b=bi[i],c=(ai[i]-ans%b+b)%b;//ax≡c(mod b)
lt gcd=exgcd(a,b,x,y),bg=b/gcd;
if(c%gcd!=0) return -1; //判断是否无解,然而这题其实不用
x=mul(x, c/gcd, bg);
ans+=x*M;//更新前k个方程组的答案
M*=bg;//M为前k个m的lcm
ans=(ans%M+M)%M;
}
return (ans%M+M)%M;
}
int main()
{
n=read();
for(int i=1;i<=n;++i)
bi[i]=read(),ai[i]=read();
printf("%lld",excrt());
return 0;
}
欧拉定理
欧拉定理表明, 若n, a为正整数,且互素, 则
a
ψ
(
n
)
≡
1
(
m
o
d
n
)
a^{\psi(n)} \equiv 1(mod\,n)
aψ(n)≡1(modn)
费马小定理降幂
使用前提:
p 是质数,且 gcd(a, p) = 1,那么 a^(p-1) ≡ 1 (mod p)
求
(
a
N
)
m
o
d
(
p
)
求(a^N)\,mod(p)
求(aN)mod(p)
a
p
−
1
≡
1
(
m
o
d
p
)
a^{p-1} \equiv1\,(mod\,p)
ap−1≡1(modp)
k
=
N
%
(
p
−
1
)
k=N\%(p-1)
k=N%(p−1)
(
a
N
)
m
o
d
(
p
)
=
(
a
k
)
m
o
d
(
p
)
(a^N)mod(p)=(a^k)mod(p)
(aN)mod(p)=(ak)mod(p)