[POJ 2891]Strange Way to Express Integers(扩展中国剩余定理)

Description

Elina is reading a book written by Rujia Liu, which introduces a strange way to express non-negative integers. The way is described as following:

Choose k different positive integers a1a2…, ak. For some non-negative m, divide it by every ai (1 ≤ i ≤ k) to find the remainder ri. If a1a2, …, ak are properly chosen, m can be determined, then the pairs (airi) can be used to express m.

“It is easy to calculate the pairs from m, ” said Elina. “But how can I find m from the pairs?”

Since Elina is new to programming, this problem is too difficult for her. Can you help her?

Solution

扩展中国剩余定理的板子题

证明的话可以看zyf2000的博客(我太懒了),个人感觉讲的还是比较清楚啦

注意数据最好还是一次性输入,这题的RE可能是因为无解break之后剩下的数据没有读入进来

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define MAXN 50005
using namespace std;
typedef long long LL;
LL k,c[MAXN],m[MAXN];
LL read()
{
    LL x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
void exgcd(LL a,LL b,LL &d,LL &x,LL& y)
{
    if(!b)d=a,x=1,y=0;
    else exgcd(b,a%b,d,y,x),y-=x*(a/b);
}
LL inv(LL a,LL p)
{
    LL d,x,y;exgcd(a,p,d,x,y);
    return (x+p)%p==0?p:(x+p)%p;
}
int main()
{
    LL m1,m2,c1,c2;
    while(~scanf("%lld",&k))
    {
        for(int i=1;i<=k;i++)
            m[i]=read(),c[i]=read();
        for(int i=2;i<=k;i++)
        {
            m1=m[i-1],m2=m[i],c1=c[i-1],c2=c[i];
            LL t=gcd(m1,m2);
            if((c2-c1)%t!=0){c[k]=-1;break;}
            m[i]=m1*m2/t;
            c[i]=inv(m1/t,m2/t)*((c2-c1)/t)%(m2/t)*m1+c1;
            c[i]=(c[i]%m[i]+m[i])%m[i];
        }
        printf("%lld\n",c[k]);
    }
    return 0;
}
posted @ 2017-06-11 21:07  Zars19  阅读(372)  评论(0编辑  收藏  举报