题目链接
https://www.luogu.org/problemnew/show/P4777
分析
扩展$CRT$就是解决模数不互质的情况,说是扩展$CRT$,其实都是扩欧…
先来考虑两个方程的情况:$x \equiv a \mod b$和$x \equiv c \mod d$
由方程1得$x=tb+a$,代入方程2中得$tb+a \equiv c \mod d$,
把它变得更像方程:$t \times b+t’ \times d = c-a$
解得$t’$后回代即可
那么对于多个方程组,假设对于前$k$个方程组我们已经求出一个解$x$,记$M= \prod_{i=1}^k m_i$,那么显然$x+i \times M$是前$k$个方程的一个通解,因为$M \equiv 0 \mod m_i (i<=k)$
那么我们要求的就是一个整数$t$,使得$x+ t \times M \equiv b _ {k+1} \mod m _ {k+1}$
移项得$t \times M + t’ \times m _ {k+1} = b _ {k+1}- x$(这里的$x$其实是已知的)
运用扩欧算出$t$,更新$x=x+t \times M$,然后$M= M \times m _ {k+1}$
当然无解的情况也就是扩欧无解的情况,当$b _ {k+1}-x$不整除$gcd(M,m _ {k+1})$时无解
注意
题目要求要将$x$化为最小整数解
代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 
 | #include <cstdio>#include <algorithm>
 #include <cctype>
 #include <cstdlib>
 #include <cstring>
 #include <cmath>
 #include <iostream>
 #define ll __int128
 #define ri register int
 using std::min;
 using std::max;
 template <class T>inline void read(T &x){
 x=0;int ne=0;char c;
 while(!isdigit(c=getchar()))ne=c=='-';
 x=c-48;
 while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
 x=ne?-x:x;return ;
 }
 const int maxn=100005;
 const int inf=0x7fffffff;
 ll b[maxn],m[maxn];
 int n;
 ll exgcd(ll a,ll b,ll &x,ll &y){
 if(b==0){x=1,y=0;return a;}
 ll d=exgcd(b,a%b,x,y);
 ll z=x;x=y,y=z-a/b*y;
 return d;
 }
 void print(ll x){
 if(!x) return;
 if(x) print(x/10);
 putchar(x%10+'0');
 }
 ll ans=0;
 int main(){
 ll x,y,M,aa,bb,cc,d;
 bool flag=0;
 read(n);
 for(ri i=1;i<=n;i++){
 read(m[i]),read(b[i]);
 }
 M=m[1],ans=b[1];
 for(ri i=2;i<=n;i++){
 aa=M,bb=m[i],cc=(b[i]-ans%bb+bb)%bb;
 x=0,y=0;
 
 
 
 d=exgcd(aa,bb,x,y);
 bb=bb/d;
 if(cc%d){flag=1;break;}
 x=((x*cc/d)%bb+bb)%bb;
 
 ans+=M*x;M*=bb;
 ans=(ans%M+M)%M;
 }
 if(flag)puts("-1");
 else {
 if(!ans)puts("0");
 else {print(ans);puts("");}
 
 }
 return 0;
 }
 
 |