http://poj.org/problem?id=2891

7
11323 9793
5537 4754
21538 10901
16118 203
2082 1209
22929 9510
16541 15898


4
18373 16147
8614 14948
8440 17480
22751 21618
6
19576 8109
18992 24177
9667 17726
16743 19533
16358 12524
8280 22731
4
9397 38490
22001 25094
33771 38852
19405 35943

ans

32439
13052907343337200
-1
78383942913636233

题目mod的数字并不互质,那怎么办呢?

记mod[i]表示第i个mod的数字,r[i]表示余数,那么观察前两项

总有X = k1 * mod[1] + r[1];

X = k2 * mod[2] + r[2];

那么k1 * mod[1] - k2 * mod[2] = r[2] - r[1]

这是可以用扩展欧几里德算法求得最小的解k1 (k1可以等于0,不一定要>0,我就是规定满足k1>0后不断溢出,所以wa)

那么得到满足前两个数字的解是(就是满足%mod[1] = r[1] , %mod[2] = r[2])的解。ansx = k1 * mod[1] + r[1]

然后往下合并

怎么往下合并呢?

就是把前面两条等式,变成了 % lcm(mod[1], mod[2]) = rr了,这个rr可以自己解出来,ansx % lcm(mod[1], mod[2])就是了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string> const int maxn = + ;
LL mod[maxn];
LL r[maxn];
LL gcd(LL n, LL m) {
if (n % m == ) return m;
else return gcd(m, n % m);
}
LL lcm(LL n, LL m) {
return n / gcd(n, m) * m;
}
LL exgcd (LL a,LL mod,LL &x,LL &y) {
//求解a关于mod的逆元 ★:当且仅当a和mod互质才有用
if (mod==) {
x=;
y=;
return a;//保留基本功能,返回最大公约数
}
LL g=exgcd(mod,a%mod,x,y);
LL t=x; //这里根据mod==0 return回来后,
x=y; //x,y是最新的值x2,y2,改变一下,这样赋值就是为了x1=y2
y=t-(a/mod)*y; // y1=x2(变成了t)-[a/mod]y2;
return g; //保留基本功能,返回最大公约数
}
bool get_min_number (LL a,LL b,LL c,LL &x,LL &y) { //得到a*x+b*y=c的最小整数解
LL abGCD = gcd(a,b);
if (c % abGCD != ) return ;//不能整除GCD的话,此方程无解
a /= abGCD;
b /= abGCD;
c /= abGCD;
LL tx,ty;
exgcd(a,b,tx,ty); //先得到a*x+b*y=1的解,注意这个时候gcd(a,b)=1
x = tx * c;
y = ty * c; //同时乘上c,c是约简了的。得到了一组a*x + b*y = c的解。
LL haveSignB = b;
if (b < ) b = -b; //避免mod负数啊
x = (x % b + b) % b; //最小解
// if (x == 0) x = b; //避免x = 0不是"正"整数 不要用这个,溢出
y = (c - a * x) / haveSignB;
return ;//1代表可以
}
int n;
void work () {
for (int i = ; i <= n; ++i) {
scanf("%lld%lld", &mod[i], &r[i]);
}
LL mm = mod[];
LL rr = r[];
LL ansx = ;
for (int i = ; i <= n; ++i) {
LL x, y;
int ret = get_min_number(mm, -mod[i], r[i] - rr, x, y);
if (ret == ) {
printf("-1\n");
return;
}
ansx = x * mm + rr;
mm = lcm(mm, mod[i]);
rr = ansx % mm;
}
printf("%lld\n", rr);
return;
} int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
while(scanf("%d", &n) != EOF && n) {
work();
}
return ;
}

为什么rr就是最小解呢?余数当然是最小的解啊。。。

POJ 2891 Strange Way to Express Integers 中国剩余定理MOD不互质数字方法的更多相关文章

  1. poj Strange Way to Express Integers 中国剩余定理

    Strange Way to Express Integers Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 8193   ...

  2. poj 2891 Strange Way to Express Integers (非互质的中国剩余定理)

    Strange Way to Express Integers Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 9472   ...

  3. poj——2891 Strange Way to Express Integers

    Strange Way to Express Integers Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 16839 ...

  4. [POJ 2891] Strange Way to Express Integers

    Strange Way to Express Integers Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 10907 ...

  5. poj 2891 Strange Way to Express Integers (扩展gcd)

    题目链接 题意:给k对数,每对ai, ri.求一个最小的m值,令m%ai = ri; 分析:由于ai并不是两两互质的, 所以不能用中国剩余定理. 只能两个两个的求. a1*x+r1=m=a2*y+r2 ...

  6. POJ.2891.Strange Way to Express Integers(扩展CRT)

    题目链接 扩展中国剩余定理:1(直观的).2(详细证明). [Upd:]https://www.luogu.org/problemnew/solution/P4774 #include <cst ...

  7. POJ 2891 Strange Way to Express Integers 中国剩余定理解法

    一种不断迭代,求新的求余方程的方法运用中国剩余定理. 总的来说,假设对方程操作.和这个定理的数学思想运用的不多的话.是非常困难的. 參照了这个博客的程序写的: http://scturtle.is-p ...

  8. poj 2891 模数不互质的中国剩余定理

    Strange Way to Express Integers Description Elina is reading a book written by Rujia Liu, which intr ...

  9. POJ 2891 Strange Way to Express Integers(拓展欧几里得)

    Description Elina is reading a book written by Rujia Liu, which introduces a strange way to express ...

随机推荐

  1. HDOJ1272(并查集,判断是否为树)

    0 0 Yes 1 1 0 0 Yes 1 2 2 1 0 0 No //自回路不算一条边的! 居然有 0 0 这样的测试数据 #include<iostream> #include< ...

  2. C++11中的原子操作(atomic operation)

    所谓的原子操作,取的就是“原子是最小的.不可分割的最小个体”的意义,它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源.也就是他确保了在同一时刻只有唯一的线 ...

  3. JAVA 1.5 并发之 Executor框架 (内容为转载)

    本文内容转自 http://www.iteye.com/topic/366591 Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Exec ...

  4. Ajax调用后台方法报未定义

    需要在web.config中<system.webServer>节点下添加如下内容 <handlers> <add name="ajax" verb= ...

  5. 阿里巴巴Druid数据库连接池的使用

    准备: 创建一个基于SpringBoot的web项目 1 引入相关依赖 jpa.mysql.druid <?xml version="1.0" encoding=" ...

  6. String与字符数组

    public class Example { static String str = new String("good"); static char[] ch = {'a','b' ...

  7. 泛型中new()约束的用法

    一..NET中支持的类型参数约束有以下几种 where T : struct              T必须是一个结构类型where T : class               T必须是一个类( ...

  8. 【转】‘svn’不是内部或外部命令,也不是可运行的程序

    解决方法:windows安装svn的时候默认是不安装 svn command line这个东西的,重新打开svn的安装exe,选择modify,将“command line client tools” ...

  9. 2018杭电多校第二场1003(DFS,欧拉回路)

    #include<bits/stdc++.h>using namespace std;int n,m;int x,y;int num,cnt;int degree[100007],vis[ ...

  10. CodeForces 116B【二分匹配】

    思路: 暴力..我不会呀.. YY一个二分匹配嘛,然后数组开小了.GG for an hour. #include <bits/stdc++.h> using namespace std; ...