前言
什么是快乐星球?
什么是欧几里得??
扩欧即是扩展欧几里得,是欧几里得算法的扩展算法。
欧几里得算法是蛤?就是小学学过的辗转相除法。用于计算两个整数a,b的最大公约数。
code:
int gcd(int a,int b)
{
if(b==0)return a;
return (b,a%b);
}
基本问题
解模方程
a
x
=
b
(
m
o
d
n
)
ax=b(mod n)
ax=b(modn)中x的正整数解
等价于求
a
x
+
n
y
=
b
ax+ny=b
ax+ny=b的x的正整数解
令
d
=
g
c
d
(
a
,
n
)
d=gcd(a,n)
d=gcd(a,n) 若
d
∣
b
d|b
d∣b 则方程有解,否则无解.
g
c
d
gcd
gcd的过程实际就是在求
a
x
+
n
y
=
g
c
d
(
a
,
n
)
ax+ny=gcd(a,n)
ax+ny=gcd(a,n)的过程
所以最后求出gcd后 x=1 y=0
code
void exgcd(int a,int b)
{
if(b==0)
{
x=1,y=0;
return;
}
exgcd(b,a%b);
int z=x;
x=y,y=z-(a/b)*y;
}
关于同余
a x ≡ b ( m o d n ) ax ≡ b (mod \;n) ax≡b(modn)
换句话说: a x m o d n = b m o d n ax \;mod\;n = b \;mod\;n axmodn=bmodn
性质: 满足同加性,同减性,同乘性,同幂性,但不满足同除性
那么
-
b m o d n = b − n q b \;mod \;n = b - nq bmodn=b−nq ( q q q为 b b b 除以 n n n )
-
a x m o d n = a x − n p ax \;mod\; n = ax - np axmodn=ax−np ( p p p为 a x ax ax 除以 n n n )
则 b − n q = a x − n p ⇒ a x − n p + n q = b b - nq=ax - np⇒ax - np+nq= b b−nq=ax−np⇒ax−np+nq=b
设 y = q − p y=q-p y=q−p,则 a x + n y = b ax+ny= b ax+ny=b
code:
》》原题洛谷【P1082同余方程】
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
int a,b,x,y;
void exgcd(int a,int b)
{
if(b==0)
{
x=1,y=0;
return;
}
exgcd(b,a%b);
int z=x;
x=y,y=z-(a/b)*y;
}
int main()
{
scanf("%d%d",&a,&b);
exgcd(a,b);
printf("%d",(x+b)%b);
}
关于逆元
可用费马小定理和欧拉定理解决
扩欧方法:(求的是x)
可转化为 a x ≡ 1 ( m o d n ) , g c d ( a , n ) = 1 ax ≡ 1 (mod n),gcd(a,n)=1 ax≡1(modn),gcd(a,n)=1
是不是看上去和同余方程很像。没错了,就是同余方程。
code:
原题》》洛谷【P3811乘法逆元】
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
ll n,p,x,y;
void exgcd(int a,int b)
{
if(b==0)
{
x=1,y=0;
return;
}
exgcd(b,a%b);
int z=x;
x=y,y=z-(a/b)*y;
}
int main(){
scanf("%lld%lld",&n,&p);
for(ll i=1;i<=n;i++)
{
exgcd(i,p);
x=(x%p+p)%p;
printf("%lld\n",x);
}
}