1. 程式人生 > >數論-模運算,歐幾里得,擴充套件歐幾里得

數論-模運算,歐幾里得,擴充套件歐幾里得

一:模運算

1:餘數:a對b取模的結果就是a除以b的餘數,記作a%b。例如24%5 == 4
2:性質:

\[ (a+b)\%p=(a\%p+b\%p)\%p \]

\[ (a-b)\%p=(a\%p-b\%p+p)\%p \]

\[ (a*b)\%p=(a\%p)*(b\%p)\%p \]

二:最大公約數

1:約數:如果a%x==0,我們稱x是a的約數(或因數)。
2:倍數:如果a%x==0,我們稱a是x的倍數。
3:a與b的最大公約數:是指一個最大整數x既是a的約數也是b的約數,記作gcd(a,b)。
4:演算法公式:

\[ gcd(a,b)=\begin{cases} a & b=0 \\ gcd(b,a\%b) &b!=0 \\ \end{cases} \]

5:程式碼實現:
int gcd(int a,int b)
{
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}
6:證明:

\[ gcd(a,b)=gcd(b,a\%b) \]


\[ gcd(a,b)=d \]

\[ a = nd, b = md,gcd(n,m) =1 \]

\[ a\%b = a-\lfloor \frac{a}{b} \rfloor*b=nd-\lfloor \frac{nd}{md} \rfloor*md=(n-\lfloor \frac{n}{m} \rfloor*m)*d=(n\%m)*d \]


所以
\[ gcd(b,a\%b)=gcd(md,(n\%m)*d)=d*gcd(m,n\%m) \]

因此只要證明
\[ gcd(m,n\%m)=1 \]
假設
\[ gcd(m,n\%m)=q,gcd(m,n\%m)!=1 \]

\[ n = k*m+r,0<=r<m \]

\[ n\%m=r,gcd(m,r) = q \]

\[ m = m1*q; r = r1*q \]
那麼
\[ n = k*m1*q+r1*q = (k*m1+r1)*q \]
那麼q就是n和m的最大公約數,與我們所假設的gcd(n,m)=1矛盾。

所以
\[ gcd(m,n\%m)=1 \]


所以
\[ gcd(a,b)=gcd(b,a\%b) \]

7:相關性質

\[ gcd(a,b,c)=gcd(a,gcd(b,c)) \]

三:最小公倍數

1:最小公倍數:將a與b的最小公倍數記作lcm(a,b).
2:與最大公約數的關係:

\[ gcd(a,b) = \frac{a}{lcn(a,b)}*b \]

注意:先除後乘防止溢位。
3:相關性質

\[ lcm(a,b,c) = lcm(a,lcm(b,c)) \]

注意:lcm(a,b,c) != abc/gcd(a,b,c)

四:擴充套件歐幾里得

1:用途:擴充套件歐幾里得演算法用於解決這樣一個問題,給定正整數a,b,求ax+by=gcd(a,b)的一組解。
2:遞迴求解(核心思想)

已知:
\[ gcd(a,b) = gcd(b,a\%b) \]

\[ a*x+b*y = gcd(a,b) =>b*x1+a\%b*y1 = gcd(b,a\%b) \]
假設x1,y1為方程組的一組解。

那麼:
\[ a*x + b*y = gcd(a,b) = b*x1+a\%b*y1 = b*x1+(a-\lfloor\frac{a}{b}\rfloor*b)*y1 = a*y1+b*(x1-\lfloor\frac{a}{b}\rfloor*y1) \]
所以:
\[ x = y1; y = x1-\lfloor\frac{a}{b}\rfloor*y1 \]
當b==0時,a=1。此時的一組解是
\[ x==1,y==0 \]

3:程式碼實現
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,y,x);
   y -= a/b*x;
   return gcd;
}
4:推廣
以上我們可以求出ax+by=gcd(a,b)的任意一組整數解,但是如何求ax1+by1=c這種呢?如果要求x>0且最小呢?
如果

\[ c\%gcd(a,b)=0 \]

否則無解。
簡單證明:

假設
\[ k = \frac{c}{gcd(a,b)} \]

\[ a*x1+b*y1=c => a*k*x2+b*y*k2 = gcd(a,b)*k = c \]
所以
\[ x1 = k*x2,y1 = k*y2 \]

如何求x非負且最小呢?
我們假設已經得到ax+by=c的一組解


\[ g =gcd(a,b) \]

\[ lcm(a,b) = \frac{a}{g}*b \]

可得
\[ a*x+lcm(a,b)+b*y-lcm(a,b) = c \]
所以
\[ a*(x+\frac{b}{g})+b*(y-\frac{a}{g}) = c \]
所以可知

x加上或減去任意倍數的b/gcd(a,b)後均有的y的解。


\[ t = gcd(a,b) \]
則x的最小非負解為
\[ (x\%t+t)\%t \]

五:擴充套件歐幾里得可以用來做什麼呢?
1:求解線性方程

HDU2669Romantic

2:求解同餘方程

POJ1061青蛙的約會

3:求逆元

https://www.cnblogs.com/AC-AC/p/10042675.html