問題描述:
已知a、b互質,求ax+by=1的一組解
擴展歐幾里得算法:
假如b=1,由於gcd(a,b)=1,因此a=x=1
假如b≠1,不妨假設a=kb+r,並且我們已經求出了bx+ry=1的一組解(x0,y0)
bx0+(a-kb)y0=1
ax1+by1=1
bx0+ay0-kby0=b(x0-ky0)+ay0=ax1+by1
x1=y0;y1=x0-ky0
那么(x1,y1)就是ax+by=1的一組解
不斷迭代即可
#include<iostream> using namespace std; int exgcd(int a,int b,int &x,int &y) { if(b==0) { x=1; y=0; return a; } int gcd=exgcd(b,a%b,x,y); int x2=x,y2=y; x=y2; y=x2-(a/b)*y2; return gcd; } int main() { int x,y,a,b; cout<<"請輸入a和b:"<<endl; cin>>a>>b; cout<<"a和b的最大公約數:"<<endl; cout<<exgcd(a,b,x,y)<<endl; cout<<"ax+by=gcd(a,b) 的一組解是:"<<endl; cout<<x<<" "<<y<<endl; return 0; }
裴蜀定理:
對於任意自然數a,b,若gcd(a,b)=d,那么對於所有整數x,y,一定存在x,y使得ax+by=d成立
設gcd(a1,a2,a3,...,an)=d,那么存在整數x1,x2,...,xn使得a1x1+a2x2+...+anxn=d
(別問我為什么)
對於整數a,我們需要找出整數b,使得a*b %p=1
即解方程ab-kp=1
1.在模為素數p的情況下,有費馬小定理
a^(p-1)=1(mod p)
那么a^(p-2)=a^-1(mod p)
也就是說a的逆元為a^(p-2)
2.而在模不為素數p的情況下,有歐拉定理
a^phi(m)=1(mod m) (a⊥m)
同理a^-1=a^(phi(m)-1)
因此逆元x便可以套用快速冪求得了x=a^(phi(m)-1)
3.在有些情況下我們要求出1到p-1所有數關於p的逆元,可以用遞推求逆元
- 設i關於p的逆元為inv[i] 則有inv[i]=(M-M/i)*inv[M%i]%M
- 設t=M/i,k=M%i,那么 t*i+k≡0(Mod M)-t*i≡k(Mod M)
- 對上式兩邊同時除 i×k,進一步得到 -t*inv[k]≡inv[i](Mod M)
- 再把和替換掉,最終得到 inv[i]=(M-M/i)*inv[M%i]%M
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> using namespace std; int A[100001]; int p; int main() { cin>>p; A[1]=1; for(int i=2;i<=10;i++) { A[i]=(p-(p/i))*A[p%i]%p; printf("%d %d %d\n",i,A[i],(i*A[i])%p); } }