poj2891 扩展欧几里得解同余方程组
2016-01-16 13:47
295 查看
题目
poj2891解同于方程组:x≡r1(moda1)x≡r2(moda2)......x≡rn(modan)其中模数不一定互质。
题解
若模数两两互质,我们可以用中国剩余定理来解。这里我们先考虑两个方程:x≡r1(moda1)x≡r2(moda2)我们可以写成:x+y1a1=r1x−y2a2=r2
相减得:y1a1+y2a2=r1−r2也就是ax+by=m的形式。
这是可以用扩展欧几里德解的。
若gcd(a,b)/|m那么方程就无解,直接输出-1。
否则我们可以解出上式的y1。回带得到一个特解x0=r1−y1a1。
通解可以写成x=x0+k∗lcm(a1,a2)也就是x≡x0(modlcm(a1,a2))。
这样我们就将两个方程合并为了一个。重复进行以上操作,我们最终能将n个方程全部合并,再用扩展欧几德得解出来就好了。
ll solve(){ ll M=a[1],R=r[1],x,y,d; for(int i=2;i<=n;i++){ d=exgcd(M,a[i],x,y); if((R-r[i])%d!=0) return -1; //无解 x=(R-r[i])/d*x%a[i]; //这才是真正的x,记得模a[i]。 R-=x*M; //特解x0,新的余数。 M=M/d*a[i]; //新的模数。 R%=M; } return (R%M+M)%M; }
下面是完整代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; ll a[100005],r[100005]; int n; ll exgcd(ll a,ll b,ll &x,ll &y){ if(b==0) return x=1,y=0,a; ll tmp=exgcd(b,a%b,y,x); y-=a/b*x; return tmp; } ll solve(){ ll M=a[1],R=r[1],x,y,d; for(int i=2;i<=n;i++){ d=exgcd(M,a[i],x,y); if((R-r[i])%d!=0) return -1; x=(R-r[i])/d*x%a[i]; R-=x*M; M=M/d*a[i]; R%=M; } return (R%M+M)%M; } int main(){ while(~scanf("%d",&n)){ for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i],&r[i]); printf("%lld\n",solve()); } return 0; }
相关文章推荐
- 【Java】动态模拟时钟
- 第二章知识总结
- Leetcode 240. Search a 2D Matrix II
- android logo:内核、android开机动画
- mysql select 语句用法
- 正则表达式收集
- ASP.NET MVC5 route使用
- android电池(五):电池 充电IC(PM2301)驱动分析篇
- Codeforces Round #339 (Div. 1) ABC
- 2016/1/16音频播放器
- uva1103 Ancient Messages
- 串
- android电池(四):电池 电量计(MAX17040)驱动分析篇
- Edittext In Listview,当listview的item中有edittext时,怎么保存edittext的值?
- JavaScript摘要
- android 电池(三):android电池系统
- opencv 图像腐蚀
- 一个经典的例子让你彻彻底底理解java回调机制
- ListView里添加EditText导致软键盘弹出闪退问题
- android 电池(一):锂电池基本原理篇