1. 程式人生 > 其它 >CRT中國剩餘定理

CRT中國剩餘定理

一、前言

引入題目:三個小朋友剛學數學沒多久,由於不會進位,只能準確10以內的數。現在有一群羊,羊主人說數量不超過兩百。小A每次數到5以後就又回到1開始數,最後剩了3只羊。小B每次數到7就回到1開始數,最後剩了5只羊。小C每次數到8之後就回到1開始數,最後剩餘7只羊。請求出這群羊有多少隻

二、分析題目

首先我們可以分析題目條件,

x % 5 == 3,為了建立同餘方程我們把BC關聯進去得到,因為bc的最小公倍數不會對b和c造成餘數,只會對a造成餘數

(b * c) % 5 == 3,化簡得:bc≡ 3 (mod 5)

也就是說我們需要在bc的公倍數中間找到一個數對5(也就是第一個人最多能數到的數5)求餘等於3

根據exgcd證明可知如果bc和 5互質,那麼可利用exgcd得

bcx + 5y = 1得到次方程的一個解,因為餘數為3,所以還需要乘以3,

依次把每一個都按照上面的步驟計算求和,最後對三個數的最小公倍數求和即可得到最小解了

程式碼如下:

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 int exgcd(int &x,int &y,int a,int b)
 4 {
 5     if(b  == 0){
 6         x = 1,y = 0;
 7         return a;
 8     }
9 int d = exgcd(y,x,b,a % b); 10 y = y - a/b * x; 11 return d; 12 } 13 int main()//用CRT解決此類問題的前提是要保證互質,當然如果不互質我們也可以採用exCRT求解 14 { 15 int b[10][2] = {{5,3},{7,5},{8,7}}; 16 int m = 1; 17 int sum = 0; 18 for(int i = 0;i <= 2;i++) 19 m *= b[i][0]; 20 int a,p; 21 for
(int i = 0;i <= 2;i++){ 22 int M = m / b[i][0]; 23 int x = M; 24 if(exgcd(a,p,x ,b[i][0])!= 1) return 0; 25 sum = sum + a * b[i][1] * M; 26 //逆元*另外兩個數的乘積*餘數 27 //前提條件是另外兩個數的乘積 和 這個數互質,滿足exgcd 28 //此時可以求得互質的一組答案,但是我們要求的是餘數為k的答案,所以我們應該乘以個k,把三個數的答案都相加即可得到該問題的一組解 29 //此時如果我們要求解最小的解,我們可以對三個數的乘積求餘,達到最小解 30 } 31 cout << (sum + m) % m << endl;//防止答案為負數,%m是求解最小解 32 return 0; 33 }

三、總結

數論yyds!