POJ 2891 扩展欧几里德
这个题乍一看跟剩余定理似的,但是它不满足两两互素的条件,所以不能用剩余定理,也是给了一组同余方程,找出一个X满足这些方程,如果找不到的话就输出-1
因为它不满足互素的条件,所以两个两个的合并,最后合成一个。
题目给定的是
M % m1 = r1
M % m2 = r2
......
M % mn = rn
只需将两个式子合并成一个式子,那么这个合并的这个式子就可以继续和下面的式子继续合并,知道合到最后一个式子。
首先来看下两个式子怎么合并。
M % m1 = r1 可以写成 M = k1 * m1 + r1;
同理M = k2 * m2 + r2
所以k1 * m1 + r1 = k2 * m2 + r2
k1 * m1 - k2 * m2 = r2 - r1
将k1 看成x, m1看成a, k2看成y, m2看成b, r2 - r1看成c
那么这个式子就变成了
ax-by=c;不定方程
这时候就可以用不定方程来解了。
因为题目给的两两可能不互素,所以gcd(a, b) 有可能不等于1,所以,这个方程不一定有解,所以就是判断这个题有没有解的条件。
如果有解的话,用扩展欧几里德可以的出这个方程的解,然后将x带入到 k1 * m1 + r1中得到M,这时候M就是这两个方程组的一个特解,通解就是M' = M + K * LCM(m1, m2);
这个式子可以变化成M' % LCM(m1, m2) = M;所以又可以继续跟下面的式子合并了。所以这个式子对应的余数r就是M, 模数(就是式子中的mi)就是LCM(m1,m2);
到这里之后就合并好了一个式子。下面就是继续按照这个过程合并到第n个式子了。最后合并完之后就剩下一个式子,求出来的M就是方程组的特解,通解为M' = M + k * LCM; 其中LCM = LCM(m1, m2...mn), 最小正整数解为(M % LCM + LCM) % LCM;
还有一个坑就是如果边输入边处理的话,不要找到无解立马就跳出循环,因为后面的数据还没输入完。
代码如下:
/*************************************************************************
> File Name: 5.cpp
> Author: Howe Young
> Mail: 1013410795@qq.com
> Created Time: 2015年08月01日 星期六 15时39分47秒
************************************************************************/ #include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1e5 + ;
typedef long long ll;
ll m[maxn], r[maxn];
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == )
{
x = ;
y = ;
return a;
}
ll r = exgcd(b, a % b, x, y);
ll t = x;
x = y;
y = t - a / b * y;
return r;
}
int main()
{
int k;
while (~scanf("%d", &k))
{
for (int i = ; i <= k; i++)
scanf("%lld %lld", &m[i], &r[i]);
ll m1, m2, r1, r2, c, d;
m1 = m[]; r1 = r[];
bool flag = true;
for (int i = ; i <= k; i++)
{
ll x, y;
d = exgcd(m1, m[i], x, y);
if ((r[i] - r1) % d != )
{
flag = false;
break;
}
c = r[i] - r1;
x = c / d * x % (m[i] / d);
r1 = m1 * x + r1;
m1 = m1 / d * m[i];
r1 %= m1;
}
if (!flag)
{
printf("-1\n");
continue;
}
r1 = (r1 + m1) % m1;
printf("%lld\n", r1);
} return ;
}
POJ 2891 扩展欧几里德的更多相关文章
- poj 2891 扩展欧几里得迭代解同余方程组
Reference: http://www.cnblogs.com/ka200812/archive/2011/09/02/2164404.html 之前说过中国剩余定理传统解法的条件是m[i]两两互 ...
- poj 1061 扩展欧几里德同余方程求解
摘要写在一瞪眼. #include<iostream> using namespace std; long long exgcd(long long a,long long b,long ...
- poj 2115 扩展欧几里德
#include<stdio.h> #include<string.h> #define max 32 typedef long long LL; LL pow2[max+]; ...
- POJ - 1061 扩展欧几里德算法+求最小正整数解
//#pragma comment(linker, "/STACK:1024000000,1024000000") //#pragma GCC optimize(2) #inclu ...
- 数学#扩展欧几里德 POJ 1061&2115&2891
寒假做的题了,先贴那时写的代码. POJ 1061 #include<iostream> #include<cstdio> typedef long long LL; usin ...
- 扩展欧几里德 POJ 1061
欧几里德的是来求最大公约数的,扩展欧几里德,基于欧几里德实现了一种扩展,是用来在已知a, b求解一组x,y使得ax+by = Gcd(a, b) =d(解一定存在,根据数论中的相关定理,证明是用裴蜀定 ...
- poj 1061 青蛙约会(扩展欧几里德)
题目链接: http://poj.org/problem?id=1061 题目大意: 中文题目,题意一目了然,就是数据范围大的出奇. 解题思路: 假设两只青蛙都跳了T次,可以列出来不定方程:p*l + ...
- POJ 2142 The Balance【扩展欧几里德】
题意:有两种类型的砝码,每种的砝码质量a和b给你,现在要求称出质量为c的物品,要求a的数量x和b的数量y最小,以及x+y的值最小. 用扩展欧几里德求ax+by=c,求出ax+by=1的一组通解,求出当 ...
- POJ 1061 青蛙的约会(扩展欧几里德)
点我看题目 题意 : 中文题不详述. 思路 : 设经过s步后两青蛙相遇,则必满足(x+m*s)-(y+n*s) = K*L(k = 0,1,2....) 变形得:(n-m)*s+K*L = x-y ; ...
随机推荐
- 得到某个进程所有线程ID和入口地址
#include <windows.h> #include <tlhelp32.h> #include "iostream" using namespace ...
- 在linux下实现UBOOT的TFTP下载功能
一.环境 1.条件 软件:虚拟机下linux(本文涉及到的是Ubuntu12.0.4). linux下的串口助手(例如minicom)或windows下的串口助手(例如超级终端.SecureCRT) ...
- Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二)
Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二) 题记: 前文<Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一)>中提 ...
- Expert Shell Scripting
Expert Shell Scripting 好好学习这本书
- [BZOJ 1833] [ZJOI2010] count 数字计数 【数位DP】
题目链接:BZOJ - 1833 题目分析 数位DP .. 用 f[i][j][k] 表示第 i 位是 j 的 i 位数共有多少个数码 k . 然后差分询问...Get()中注意一下,如果固定了第 i ...
- MYSQL的硬盘IO过高引起的CPU过高判断
其实,为客户提供相关日志,不就是RACKSPACE主要作的事? 俺们以后也可以效仿的.不要去解决,而是协助客户定位. http://blog.const.net.cn/a/17275.htm 上文的思 ...
- SetTimer and CreateWaitableTimer的例子(静态函数设置为回调函数,瑞士的网页,有点意思)
Timers (SetTimer and CreateWaitableTimer) in Windows SetTimer The following example creates a time ...
- 想做Android Wear开发?你得先搞明白这四件事
手环和手表的腕上穿戴之争,随着Apple Watch发布和Android Wear不断完善而告一段落.尽管续航上略有缺陷,但手表以其类似手机可扩展的生态环境赢得了众多巨头的支持. Google曾透露, ...
- POJ3087 Shuffle'm Up(模拟)
题目链接. AC代码如下; #include <iostream> #include <cstdio> #include <cstring> #include &l ...
- 大小中型数据库和Oracle的常用命令
一:大小中型数据库 二:基本命令 连接命令 1.conn[ect] 用法:conn 用户名/密码@网络服务器名[as sysdba/sysoper]当用特权用户身份连接时,必须带上as sysdba或 ...