1. 程式人生 > >POJ 2891 Strange Way to Express Integers excrt/我真傻,真的

POJ 2891 Strange Way to Express Integers excrt/我真傻,真的

namespace tran ostream express register 去重復 剩余定理 正常的 方程

我真傻,真的

我單知道這道題在(b-b1)%d!=0時要判無解,哪成想自己卻沒有讀完這組後面的數據而直接break掉。。。qwqfk


x≡b1 (mod a1)

x≡b2 (mod a2)

....

x≡bn (mod an)

a1,a2,...,an不互質時,正常的中國剩余定理是用不了的

所以有了EX版

求解:

我們先看第1,2個方程,它們可以轉化為:

x=a1*k1+b1, (I)

x=a2*k2+b2;

進而a1*k1+b1=a2*k2+b2,所以有:

a1*k1-a2*k2=b2-b1

進一步就是 a1*k1+a2*(-k2)=b2-b1 (II)

把他轉化為exgcd求解的形式:ax+by=c,a就是a1,x就是k1,b就是a1,y就是-k2,c就是b2-b1;

此時可以求出(I)的一組特解,即a1*k1+a2*(-k2)=gcd(a1,a2)時,k1的值。

顯然,當(b2-b1)不能被gcd(a1,a2)整除時,(1)無解;

若有解,(I)的解就是 k1*(b2-b1)/gcd(a1,a2),

註意此時算出來k1mod (a2/gcd(a1,a2)),這相當於是給k1減去了floor(k1/(a2/gcd(a1,a2)))*(a2/gcd(a1,a2)),給k2加上了floor(k1/(a2/gcd(a1,a2)))*(a1/gcd(a1,a2)),防止爆

long long;

然後將k1帶回原式,則x=a1*k1+b1

此時,你得到了滿足第1,2兩個方程的解,

那麽我們顯然又有一個結論:

最終的ans ≡ x (mod lcm(a1,a2))

所以我們又有了:
x≡b12 (mod a12) (*)

其中b12=第1,2兩個方程的解,即上一行的x;a12=lcm(a1,a2)

那麽我們就可以拿(*)和條件中的第3個方程去重復上面的操作。

一直重復下去,直到解出最終的解

註:代碼中的a相當於a1,a1相當與a2

#include<cstdio>
#include<iostream>
#define
ll long long #define R register ll using namespace std; inline ll g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch==-?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } inline ll exgcd(ll a,ll b,ll& x,ll& y) { if(b==0) {x=1,y=0; return a;} R d=exgcd(b,a%b,y,x); y-=(a/b)*x; return d; } int n; signed main() { while(~scanf("%d",&n)) { register bool flg=false; R a=g(),b=g(),k,k1; for(R i=2;i<=n;++i) { R a1=g(),b1=g(); if(flg) continue; R d=exgcd(a,a1,k,k1); if((b1-b)%d) flg=true; else { k=(b1-b)/d*k%a1; b+=a*k; a=a*a1/d; b%=a; } } if(flg) printf("-1\n"); else printf("%lld\n",(b%a+a)%a); } }

2019.05.15紀念自己的沙雕石刻qwq

POJ 2891 Strange Way to Express Integers excrt/我真傻,真的