POJ_2891_中国剩余定理
来源:互联网 发布:mysql union all 性能 编辑:程序博客网 时间:2024/06/05 14:56
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?
Input
The input contains multiple test cases. Each test cases consists of some lines.
Line 1: Contains the integer k.
Lines 2 ~ k + 1: Each contains a pair of integers ai, ri (1 ≤ i ≤ k).
Output
Output the non-negative integer m on a separate line for each test case. If there are multiple possible values, output the smallest one. If there are no possible values, output -1.
Sample Input
2
8 7
11 9
Sample Output
31
解题思路
中国剩余定理:
能求解什么问题呢?
问题:
一堆物品
3个3个分剩2个
5个5个分剩3个
7个7个分剩2个
问这个物品有多少个?
模线性方程组
设总数为n,则n%3=2,n%5=3,n%7=2;m%a1=r1;
m%a2=r2;
m%a3=r3;m%an=rn;
所以
m=k1*a1+r1;
m=k2*a2+r2;
=>k1*a1+r1=k2*a2+r2;
=>k1*a1+k2*a2=r2-r1;
=>a1*x+a2*y=c;(扩展欧几里得)
先通过c%gcd(a1,a2)看是否存在解,若存在解,求出x,可得到m=a1*x+r1;解出m。
将m作为一个特解,可得一个解系:M=m+k*lcm(a1,a2)(k为任意整数);
lcm(a,b)是a,b最小公倍数,lcm(a,b)=a*b/gcd(a,b);
变形得到M%lcm(a1,a2)=m;得到一个新的模方程,令A=lcm(a1,a2),R=m;
M%A=R(m)
所以m%a1=r1;m%a2=r2;可以合并成M%lcm(a1,a2)=m;
这样每两个合并,重复操作即可得到最终结果。
代码中
r1=x*a1+r1;
a1=a1*a2/d;
即为M%lcm(a1,a2)=m;
所以r1=m;
a1=lcm(a1,a2)=a1*a2/gcd(a1,a2);
代码
#include <iostream>#include <cstdio>using namespace std;long long gcd(long long a,long long b,long long& x,long long& y )//扩展欧几里得{ if(b==0) { x=1; y=0; return a; } else { long long d=gcd(b,a%b,y,x); y-=x*(a/b); return d; }}int main(){ int n; long long a1,a2,r1,r2,solve; long long c; long long x,y; //两个数据计算出一个n,两次求得的结果与下一次输入的合并, while(scanf("%d",&n)!=EOF) { solve=0; scanf("%lld%lld",&a1,&r1); for(int i=1;i<n;i++) { scanf("%lld%lld",&a2,&r2); c=r2-r1; long long d=gcd(a1,a2,x,y); if(c%d!=0) solve=1; x=x*(c/d); x=(x%(a2/d)+(a2/d))%(a2/d);//最小整数解 r1=x*a1+r1;//更新r1,两个数据求得的m a1=a1*a2/d;//更新a1 } if(solve==1) printf("-1\n"); else printf("%lld\n",r1); } return 0;}
- POJ_2891_中国剩余定理
- 中国剩余定理模版【中国剩余定理】
- 中国剩余定理
- 中国剩余定理
- 中国剩余定理
- 中国剩余定理
- 中国剩余定理
- 中国剩余定理
- 中国剩余定理
- 中国剩余定理
- 数论-中国剩余定理
- 中国剩余定理
- 中国剩余定理
- 中国剩余定理
- 数论/中国剩余定理
- 关于《中国剩余定理》
- 中国剩余定理
- 模板[中国剩余定理]
- nginx-suselinux下安装
- Hello CSDN
- Android限定EditText的输入类型为数字或者英文(包括大小写)
- photon服务器具体实例
- ubuntu apt-get dpkg应用中的一些问题及解决方法
- POJ_2891_中国剩余定理
- Redis笔记
- 69. Sqrt(x) leetcode
- git里的三个区域
- Java 常用类库、向量与哈希
- 安卓手机监听软件开发技术
- windows清除dns缓存,否则不是及时的
- 携程2016研发工程师笔试题
- Linux随记