POJ 2891 Strange Way to Express Integers

窮源溯流發表於2020-10-18

 

題意:

  

題目給定多個式子,x\equivai(mod mi), 因為不確定其中 ai,mi 的關係,也就是說不清楚是否互質,所以,例如有兩個式子

x=r1+k1*a1   -----(1)

x=r2+k2*a2   -----(2)

求 x ,根據擴充套件歐幾里得原理,兩式相等得:k1*a1-k2*a2=r2-r1,其中要滿足 r2-r1=k*gcd(a1,a2)

所以利用函式 ex_gcd 求解 x 的答案,進而求得 k1 的值,這樣 (1) 式就有了答案,因為 (1)式中的 x 的值同樣要滿足(2) 式,所以 x=x‘( (1)式中 x 的值 )+k*lcm(a1,a2)

變為 x\equivx'(mod lcm(a1,a2))

inline void write(ll x)
{
    if(x<0){ putchar('-');x=-x; }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}

const int N=1e5+5;
const ll mod=21252;
 
    int n,m,t;
    int i,j,k;
    ll a[N],r[N];

ll ex_gcd(ll a,ll b,ll &x,ll &y) //ax+by=gcd(a,b)
{
    ll gcd=a;
    if(!b) x=1,y=0;
    else {
        gcd=ex_gcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    return gcd;
}

void rep(ll &x,ll mod)
{
    x%=mod;
    x+=mod;
    x%=mod;
    if(!x) x=mod;
}

ll China()
{
    ll A=a[1],x,y,ans=r[1];
    for(int i=2;i<=n;i++){
        ll d=ex_gcd(A,a[i],x,y); // Ax+a[i]y=gcd(A,a[i])
        if((r[i]-ans)%d) return -1;

        x=x*(r[i]-ans)/d; //將求解的 x 擴大 k 倍
        rep(x,a[i]/d);
        ans=x*A+ans;
        A=A/d*a[i];
        rep(ans,A);
    }
    return ans;
}

int main()
{
    //IOS;
    while(~sd(n)){
        for(i=1;i<=n;i++) sll(a[i]),sll(r[i]);
        write(China());
        puts("");
    }
    //PAUSE;
    return 0;
}

 

相關文章