扩展欧几里得(ex_gcd),中国剩余定理(CRT)讲解 有代码

扩展欧几里得算法

  求逆元就不说了。

  ax+by=c

  这个怎么求,很好推。

  设d=gcd(a,b) 满足d|c方程有解,否则无解。

  扩展欧几里得求出来的解是 x是 ax+by=gcd(a,b)的解。

  对于c的话只需要x*c/gcd(a,b)%(b/d)即可,因为b/d的剩余系更小。

  为什么这样呢?

  设a‘=a/d,b‘=b/d 求出a‘x+b‘y=1的解,两边同时乘d,然后x也是ax+by=d的解,

  然后因为b‘的剩余系更小,所以%b’

中国剩余定理是合并线性方程组的

中国余数定理

  转化为一个线性方程 ax+by=c

   a,b

   c,d

   num % a=b;

   num % c=d;

   求num最小正整数解;

   num=ax+b=cy+d

   ax-cy=d-b

   可以化为求解 ax≡(d-b)(mod c);

   ax+cy=d-b

   用ex_gcd求解出x;

   num=a*x+b;

   这样num mod a=b

   num mod c=d-b+b=d

   因为x为最小正整数解,所以num为最小解

   满足的集合为{x|x=num+k·[a,b],(k∈Z)}

   然后转化为%lcm(a,c)=num

   然后继续合并

附上代码,完美代码

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cmath>
 5 typedef long long ll;
 6 using namespace std;
 7 ll ex_gcd(ll a,ll b,ll &x,ll &y)
 8 {
 9     if (!b)
10     {
11         x=1,y=0;
12         return a;
13     }
14     ll fzy=ex_gcd(b,a%b,x,y);
15     ll t=x;
16     x=y;y=t-a/b*y;
17     return fzy;
18 }
19 int main()
20 {
21     int t;
22     ll z1,z2,z3,z4;
23     while (cin>>t)
24     {
25         bool flag=0;
26         scanf("%lld%lld",&z1,&z2);
27         for (int i=1;i<t;i++)
28         {
29             scanf("%lld%lld",&z3,&z4);
30             if (flag) continue;
31             ll a=z1,b=z3,c=z4-z2;
32             ll x,y;
33             ll d=ex_gcd(a,b,x,y);
34             if (c%d!=0)
35             {
36                 flag=1;
37                 continue;
38             }
39             ll t=b/d;
40             x=(x*(c/d)%t+t)%t;//t的剩余系更小。
41             z2=z1*x+z2;//得出num
42             z1=z1*(z3/d);
43             cout<<"z1="<<z1<<" z2="<<z2<<endl;
44         }
45         if (flag==1) cout<<-1<<endl;
46         else cout<<z2<<endl;
47     }
48 }

原文地址:https://www.cnblogs.com/fengzhiyuan/p/8525187.html

时间: 2024-08-05 16:12:12

扩展欧几里得(ex_gcd),中国剩余定理(CRT)讲解 有代码的相关文章

hdu1573-X问题-(扩展欧几里得定理+中国剩余定理)

X问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8416    Accepted Submission(s): 3066 Problem Description 求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X mod a[1] = b[1], X mod a[2] = b[2], -, X mod

hdu3579-Hello Kiki-(扩展欧几里得定理+中国剩余定理)

Hello Kiki Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5489    Accepted Submission(s): 2164 Problem Description One day I was shopping in the supermarket. There was a cashier counting coins

poj2115 C Looooops——扩展欧几里得

题目:http://poj.org/problem?id=2115 就是扩展欧几里得呗: 然而忘记除公约数... 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll A,B,C,k,a,b,x,y,g,s; ll gcd(ll a,ll b){return a%b?gcd(b,a%b):b;} void exgc

gcd,扩展欧几里得,中国剩余定理

1.gcd: int gcd(int a,int b){ return b==0?a:gcd(b,a%b); } 2.中国剩余定理: 题目:学生A依次给n个整数a[],学生B相应给n个正整数m[]且两两互素,老师提出问题:有一正整数ans,对于每一对数,都有:(ans-a[i])mod m[i]=0.求此数最小为多少. 输入样例: 1 10 2 3 1 2 3 2 3 5 8 1 2 3 4 5 6 7 8 97 89 67 61 59 53 47 88 12 1 2 3 4 5 6 7 8 9

扩展欧几里得及中国剩余定理

Exgcd 扩展欧几里得 void exgcd(int a,int b,int &x,int &y){ if(!b){x=1,y=0;return;} exgcd(b,a%b,x,y);b-=y*(a/b); } 对于 \(gcd(a,b)=g\) ,\(a\times k_1+b\times k_2 =g\) 通过 \(exgcd(a,b,x,y)\) \(k_1=x+k\times b\) 对于 \(gcd(a,b)=g\) ,\(a\times k_1+b\times k_2=C\t

Uva10673 - Play with Floor and Ceil ( 扩展欧几里定理 )

Uva10673 - Play with Floor and Ceil ( 扩展欧几里定理 )  实际上是一道很裸的扩展欧几里德定理的题目,结果把Floor和Ceil搞反了WA一次悲剧啊 #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; void ex_gcd(LL a, L

UVALive 6428 A+B 【扩展欧几里得】

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4439 题目大意:给出a,b,S三个数,每次可以选择从a的位置加到b上,也可以从b的位置加到a上,问a或者b的位置上能否达到S. 比如:给出a和b,可以得到的是 (a b) (a+b b) (a a+b) (a+2b b)   (a+b a+2*b)     (2a+

扩展欧几里得的一些心得

最近发现扩展欧几里得的使用过程中有一些要注意的地方. 1.ax+by=c,这个式子中,如果b是负数,那么把它当作正数来算也无妨,因为只要给y乘一个(-1)就可以了.当然a也是同理. 2.如果解出来的x是一个负数,那么怎么变成正数呢? 方法如下: 得出来的解是ax+by=gcd(a,b)的解,令g=gcd(a,b),那么两边同时乘以(c/g)可以得到(ac/g)*x+(b/g)*(y*c)=c. 先对ax+by=c考虑,我们可以转化成a(x+b)+b(y-a)=c.因此x可以是在原数字的基础上加减

扩展欧几里得 HDU 1576

题意;要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1). 因为:A%9973=n; 所以:9973*y+n=A: 设:A/B=x;(可以整除) 所以:9973*y+n=B*x; 所以:B*x-9973*y=n; ①式 又因为:gcd(B,9973) = 1; 所以必存在 x1*B+9973*y1=1;②式 ②式*n=①式 所以只要求出x1,就可以得到x,又因为x=a/b,只要在 mod 9973就是答案了. 现