ex中国剩余定理--P4777 【模板】扩展中国剩余定理(EXCRT)

*传送

* 让我们来改变一下格式:

• x+y1a1=b1①
• x-y2a2=b2②
• x-y3a3=b3③
• …

 ①②相减得:

• y1a1+y2a2=b1-b2 

用exgcd求解,不能解就无解。然后我们可以解出一个最小正整数y1,带入①得到x其中一个解:

• x0=b1-y1a1

它的全解为x=x0+k*lcm(a1,a2)(由y1的全解可导)即x=x0(mod lcm(a1,a2)), 则:

• x+y3*lcm(a1,a2)=x0④

③④再联立,重复以上过程即可。

excrt部分的代码如下:

 1 void excrt() {
 2     for(int i = 2; i <= n; i++) {
 3         A = m[1], B = m[i], C = a[i]-a[1];
 4         C = (C%B+B)%B;
 5         int g = exgcd(A,B,x,y);
 6         x = x*(C/g);
 7         x = (x%B+B)%B;
 8         a[1] = a[1]+ m[1]*x;
 9         m[1] = m[1]*(m[i]/g);
10         a[1] = (a[1]%m[1]+m[1])%m[1];
11     }
12 }

完整代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #define int long long
 6 using namespace std;
 7 const int maxn = 1e6;
 8 int n,x,y,A,B,C;
 9 int m[maxn],a[maxn],ans;
10 int qm(int a,int b,int mo){
11     int ans = 0,base = a;
12     while(b){
13         if(b&1) ans = (ans+base) %mo;
14         base = (base+base) %mo;
15         b >>= 1;
16     }
17     return ans;
18 }
19 int exgcd(int a,int b,int &x,int &y) {
20     if(!b) {
21         x=1, y=0;
22         return a;
23     }
24     int g = exgcd(b,a%b,x,y);
25     int tx = x;
26     x = y;
27     y = tx-(a/b)*y;
28     return g;
29 }
30 void excrt() {
31     for(int i = 2; i <= n; i++) {
32         A = m[1], B = m[i], C = a[i]-a[1];
33         C = (C%B+B)%B;
34         int g = exgcd(A,B,x,y);
35         x = qm(x,(C/g),B);
36         x = (x%B+B)%B;
37         a[1] = a[1]+ qm(m[1],x,m[1]*(m[i]/g));
38         m[1] = m[1]*(m[i]/g);
39         a[1] = (a[1]%m[1]+m[1])%m[1];
40     }
41 }
42 main() {
43     scanf("%lld",&n);
44     for(int i = 1; i <= n; i++)
45         scanf("%lld%lld",&m[i],&a[i]);
46     excrt();
47     printf("%lld",a[1]);
48 }

猜你喜欢

转载自www.cnblogs.com/very-beginning/p/12403791.html