http://acm.pku.edu.cn/JudgeOnline/problem?id=2891 欧几里德线性同余方程
2010-08-11 12:50
447 查看
]/* 对于同余方程组: x=a1 (mod m1) x=a2 (mod m2) 方程组有一个小于m(m1,m2的最小公倍数)的非负整数解的充要条件是(a1-a2)%gcd(m1,m2)=0,同样利用扩展欧几里得算法。两式联立:a1+m1*y=a2+m2*z 则:a1-a2=m2*z-m1*y这样就可以解出z和y,则:x=a2+m2*z 而对于一般情形:(设m1,m2,...mk两两互素)时有: a=b[1] (mod w[1]) a=b[2] (mod w[2]) ..... a=b (mod w ) 其中w,b已知,w[1],w[2]...w 是两两互素的正整数,求a 令W=w[1]*w[2]*...w ,用W[i]=W/w[i],因为gcd(W[i],w[i])=1,故有;两整数p[i],q[i]满足W[i]*p[i]+w[i]*q[i]=1;如果记e[i]=W[i]*p[i],那么当j!=i时有:e[i]=0 (mod w[j]),当j=i时有:e[i]=1 (mod w[j]); 所以很明显:e[1]*b[1]+e2*b[2]+......e[k]*b[k]就是方程的一个解,加减W倍后就可以得到最小非负整数解了 而对于w[1],w[2].....w 不互素的情形,就只能两个两个来求了 x=a[1] (mod m[1]) x=a[2] (mod m[2]) 解完后,a=x,m=m1和m2的最小公倍数 将题目意思转化为公式:a1*x-a2*y=r2-r1,用欧几里得扩展算法求解 题意是说,给一组a[i],r[i],求一个最小的m,满足 for_each(i=0: n) m % a[i] = r[i] 即 a[i]*x+r[i]=m,不存在输出-1。 我们首先得到 a1 * x + r1 = m 和 a2 * y + r2 = m,联立得到 a1 * x - a2 * y = r2 - r1,利用ex_gcd解之,先解得a1*X-a2*Y=GCD(a1,a2)时的X Y值和a1,a2的gcd,x y存在整数解的条件是 gcd | r2-r1.是否输出-1就是从这判断。有解即为 x=(r2-r1)/gcd*X tmp=a2/gcd, x=( ( r2 - r1 ) / gcd * X % tmp + tmp ) % tmp; 接着输入下一组a3,r3,问题变为求满足LCM(a1,a2)%m1=m和 a3%m1=r3的新的m值:m1 LCM(a1,a2) * x + a3 * y = r3 - m 这样只要a1 a2 r1 r2 轮流迭代即可,不用开数组。题目也没说k多大,暗示本题不用开数组。每次更新a1为LCM(a1,a2),r1为m即可。不过注意求x时 http://blog.csdn.net/shifuwawa/archive/2010/06/10/5662314.aspx 看了别人深刻的分析总算有点懂了,估计自己敲还是有点困难的 */ #include <iostream> #include <cstdio> using namespace std; __int64 x,y,t; __int64 extend_gcd(__int64 a,__int64 b) //return gcd(a,b) 得到x,y { if(b == 0) { x = 1; y = 0; return a; } else { __int64 temp = extend_gcd(b,a%b); t = x; x = y; y = t - a/b*y; return temp; } } int main() { __int64 a1,a2,r1,r2,c,gcd,temp; bool yes; int n; while(scanf("%d",&n) != -1) { yes = false; scanf("%I64d %I64d",&a1 ,&r1); for(int i=0 ;i<n-1 ;i++) { scanf("%I64d %I64d",&a2 ,&r2); if(yes) continue; c = r2 - r1; gcd = extend_gcd(a1,a2); if(c%gcd != 0) { yes = true; continue; } temp = a2/gcd; x = (c/gcd*x % temp + temp)%temp; r1 = a1*x + r1; a1 = a1*a2/gcd; } if(yes) printf("-1/n"); else printf("%I64d/n",r1); } return 0; }
相关文章推荐
- http://acm.pku.edu.cn/JudgeOnline/problem?id=1284 (原根)
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2480 欧拉
- http://acm.pku.edu.cn/JudgeOnline/problem?id=1131 八进小数转十进制小数
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2777 成段更新,区间统计颜色的种类 (用的位运算, 可是写的很搓)
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2305 大数的b进制数 取模
- http://acm.pku.edu.cn/JudgeOnline/problem?id=3667 区间更新+求满足长短的最左区间
- http://acm.pku.edu.cn/JudgeOnline/problem?id=3468 成段更新,区间求和(要用long long)
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2409 polya或者burnside
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2407 很水的欧拉
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2528 成段更新,区间统计颜色的种类(离散化处理线段)
- http://acm.pku.edu.cn/JudgeOnline/problem?id=1808 二次剩余式
- http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=10102&courseid=0
- Fire Net from http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=2
- 三塔DP——http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3554
- http://acm.pku.edu.cn/JudgeOnline/
- http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=10594&courseid=4
- Crashing Balloon from http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3
- http://acm.fafu.edu.cn/showproblem?problem_id=1005食物链 (第一次用类写,居然过了
- nefu 2 http://acm.nefu.edu.cn/test/problemshow.php?problem_id=2
- nefu 118 质数在阶乘中的幂 http://acm.nefu.edu.cn/test/problemshow.php?problem_id=118