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!

posted @ 2021-12-27 21:12  scannerkk  阅读(58)  评论(0)    收藏  举报