最近在学习算法,不管是算法竞赛中还是平常刷题中都绕不开数论,数论在算法中也是常考题了,但是我们平常在大学里一般没有这门课程,所以说学习这门课还是比较困难的,总不能跑到数学院中偷听把。今天我要分享的学习笔记的主题就是 同余
目录
基本概念:
在数学中,符号 "|" 表示整除关系。解释这两个表达式前,先了解一下符号定义:
a| b: 表示a 可以整除b。
如果 a|b 以及 b|a表示a与b相等 即a==b.
同余指的就是,有两个数,这两个数模以同一个数的结果是相同的,那么这两个数之间就有
一种关系,叫同余。用公式表示就是 a≡b(mod d)
同余的性质:
自反性:a ≡ a ( m o d m ) a≡a(mod \quad m)a≡a(modm)
对称性:a ≡ b ( m o d m ) ⇔ b ≡ a ( m o d m ) a≡b(mod \quad m)\Leftrightarrow b≡a(mod \quad m)a≡b(modm)⇔b≡a(modm)
传递性:a ≡ b ( m o d m ) 且 b ≡ c ( m o d m ) ⇒ a ≡ c ( m o d m ) a≡b(mod \quad m)且 b≡c(mod \quad m)\Rightarrow a≡c (mod \quad m)a≡b(modm)且b≡c(modm)⇒a≡c(modm)同乘性:a≡b(modm)⇒na≡nb(modm)其中a为整数
同幂性:a≡b(modm)⇒an≡bn(modm)其中a为整数
原文链接:https://blog.csdn.net/weixin_43627118/article/details/103357784
不定方程:
不定方程,又称为丢番图方程,通俗的说就是多个未知数的方程,求解只在整数范围内进行。
比如: ax+by=c 的二元一次的不定方程。
裴蜀定理:
简单来说:只有等式右边是a和b的最大公约数或者最大公约数的倍数,x和y才有整数解
所以后面很多题都要转换成上方这种形式,然后再进行后续操作才可以。
欧几里得算法:
gcd(a,b)=gcd(b,a%b) (gcd(a,b)代表最大公约数)
这里比较重要,同过将求a,b的最大公约数先求其等价子问题b,a%b,因为取余会将这两个数越来越小,知道最后当b=0的时候,a就是答案
扩展欧几里得算法:
这里面的通解可能难以理解,以下是证明过程:
接下俩是一道例题,运用上方的扩展欧几里得算法:
#include<bits/stdc++.h>
using namespace std;
using ll= long long ;
ll ans;
ll exgcd(ll a,ll b,ll &x,ll &y){//注意这里是用&引用接收的x和y
if(!b){//当b=0时,a就是最大公约数
x=1;
y=0;
return a;
}
ll x1,y1;
ans=exgcd(b,a%b,x1,y1);//向更深处递归,直到b=0
x=y1;// 公式求解x和y
y=x1-a/b*y1;
return ans;//这个返回的ans永远是最大公约数
}
int main(){
ll n,m,x,y,l;
cin>>x>>y>>m>>n>>l;//接收
ll b=n-m,a=x-y;
if(b<0){//保证a和b都是正的
b=-b;
a=-a;
}
ll x1,y1;
exgcd(b,l,x1,y1);
if(a%ans!=0){
cout<<"Impossible";
}else cout <<((x1*(a/ans))%(l/ans)+(l/ans))%(l/ans);//保证返回是正数
}
同余定理:
题:求关于 xx 的同余方程 ax≡1(modb) 的最小正整数解。
这种题应该如何解呢?
1.就是将同余方程转化为不定方程
由ax ≡ b (mod m) 得ax=m(-y)+b
即 ax+my=b
由裴蜀定理,当gcd(a,m)|b时有解
2.用扩欧算法
求ax+my =gcd(a,m)的解,把x乘以b/gcd(a,m)即可得到原方程的特解
下方就是题和代码:203. 同余方程 - AcWing题库
#include<bits/stdc++.h>
#define int long long
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;
}
signed main(){
int a,b,x,y;
cin>>a>>b;//接收数据
exgcd(a,b,x,y);
cout<<((x%b+b)%b);//不管x是否为正数还是负数,这样操作后一定是最小整数
return 0;
}