同余定理 逆元 中国剩余定理 费马小定理

同余定理

同余定理是数论中的重要概念。给定一个正整数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=(ab)%p

费马小定理求逆元:

b的逆元 = b p − 2 b^{p-2} bp2

线性递推

#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),问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。具体解法分三步:

  1. 找出三个数:从3和5的公倍数中找出被7除余1的最小数15,从3和7的公倍数中找出被5除余1 的最小数21,最后从5和7的公倍数中找出除3余1的最小数70。
  2. 用15乘以2(2为最终结果除以7的余数),用21乘以3(3为最终结果除以5的余数),同理,用70乘以2(2为最终结果除以3的余数),然后把三个乘积相加15∗2+21∗3+70∗2得到和233。
  3. 用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) ap11(modp)
k = N % ( p − 1 ) k=N\%(p-1) k=N%(p1)
( 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)

Guess you like

Origin blog.csdn.net/qq_45560445/article/details/121589145