[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 a1, a2, …, ak. For some non-negative m, divide it by every ai (1 ≤ i ≤ k) to find the remainder ri. If a1, a2, …, ak are properly chosen, m can be determined, then the pairs (ai, ri) 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; }