1. 程式人生 > >【模板】合併模線性方程組(POJ2891)

【模板】合併模線性方程組(POJ2891)

Description

  給定\(n\)組同餘關係,求解最小的非負整數\(x\),滿足\(x \mod a_i = r_i\)

Input

  第一行一個整數\(n\)
  接下來\(n\)行,每行兩個整數,分別表示\(a_i\)\(r_i\)

Output

  一個正整數\(x\)即最小正整數解。若無解則輸出\(-1\)

Solution

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
long long a[100010],r[100010],x,y;
long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if (b==0)
    {
        x=1,y=0;
        return a;
    }
    long long p=exgcd(b,a%b,x,y);
    long long z=x;
    x=y,y=z-(a/b)*y;
    return p;
}
int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        bool flag=1;
        for (int i=1;i<=n;i++)
            scanf("%lld%lld",&a[i],&r[i]);
        for (int i=1;i<n;i++)
        {
            x=0,y=0;
            long long d=exgcd(a[i],a[i+1],x,y),t=a[i+1]/d;
            if ((r[i+1]-r[i])%d) 
            {
                flag=0;
                break;
            }
            else
            {
                x=x*((r[i+1]-r[i])/d);
                x=(x%t+t)%t;
                r[i+1]=a[i]*x+r[i];
                a[i+1]=a[i]*a[i+1]/d;
                r[i+1]%=a[i+1];
            }
        }
        if (!flag) printf("-1\n"); else printf("%lld\n",r[n]);
    }
    return 0;
}