【模板】合并模线性方程组(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;
}

猜你喜欢

转载自www.cnblogs.com/Code-Geass/p/9933946.html
今日推荐