星星之火

[poj 2891] Strange Way to Express Integers 解题报告(excrt扩展中国剩余定理)

题目链接:http://poj.org/problem?id=2891

题目大意:

求解同余方程组,不保证模数互质

题解:

扩展中国剩余定理板子题

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;

const int N=100000+15; 
int k;
ll m[N],a[N];
inline ll read()
{
    char ch=getchar();
    ll s=0,f=1;
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*f;
}
ll mul(ll a,ll b,ll mod)
{
    ll re=0;
    for (;b;b>>=1,a=(a+a)%mod) if (b&1) re=(re+a)%mod;
    return re;
}
ll exgcd(ll a,ll b,ll &x0,ll &y0)
{
    if (!b)
    {
        x0=1;y0=0;
        return a;
    }
    ll gcd=exgcd(b,a%b,y0,x0);
    y0-=a/b*x0;
    return gcd;
}
ll excrt()
{    
    ll M=m[1],x=a[1];
    for (int i=2;i<=k;i++)
    {    
        ll mi=m[i],ai=a[i];
        ll x0,y0;
        ll gcd=exgcd(M,mi,x0,y0);
        ll c=(ai-x%mi+mi)%mi;
        if (c%gcd) return -1;
        x0=mul(x0,c/gcd,mi/gcd);
        //x0=x0*c/gcd%(mi/gcd);
        x+=x0*M;
        M=M/gcd*mi;
        x%=M;
    }
    return (x%M+M)%M;
}
int main()
{
    //freopen("excrt.in","r",stdin);
    //freopen("excrt.out","w",stdout);
    //scanf("%d",&k);
    while (~scanf("%d",&k))
    { 
        for (int i=1;i<=k;i++) m[i]=read(),a[i]=read();
        printf("%lld\n",excrt());
    } 
    return 0;
}

 

posted @ 2018-09-14 14:58  星星之火OIer  阅读(217)  评论(0编辑  收藏  举报