题目链接
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$化为最小整数解
代码
1 2 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; }
|