解同余式的最小解

  我们知道欧几里得扩展定理是同余方程ax≡b(mod c)解得有力方法。这个方程可能有解也可能没有解,下面给出有解的条件:

  定理:同余方程ax≡b(mod c)有解,当且仅当gcd(a,c)|b,且方程有gcd(a,c)个解。

  原因是求ax≡b(mod c)可以转化为求ax+cy=b。

  令:d=gcd(a,c),  k=c/d;

  我们可以用扩展欧几里得求出x,y值。那么方程ax≡b(mod c)的一个特解:x0=x*(b/d)%c。并且它的d个解分别为:

  Xi=(x0+i*(k))%c,{i=0,1,2,.....d-1}。

  方程ax≡b(mod c)的最小解为:(x0%k+k)%k。

代码如下:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 using namespace std;
 5 
 6 __int64 Exgcd(__int64 a, __int64 b, __int64 &x, __int64 &y)
 7 {
 8     if(b==0)
 9     {
10         x=1, y=0;
11         return a;
12     }
13     __int64 r = Exgcd(b, a%b, x, y);
14     __int64 tp=x;
15     x = y;
16     y = tp-a/b*y;
17     return r;
18 }
19 
20 // ax==b(mod c)
21 void Liner_modu(__int64 a, __int64 b, __int64 c)
22 {
23     __int64 x, y, ans;
24     __int64 d = Exgcd(a, c, x, y);
25     if(b%d)
26     {
27         puts("No solution");
28         return;
29     }
30     ans = x*(b/d)%c;  //特解
31     y = c / d;
32     ans = (ans%y+y)%y; //最小解
33     printf("%I64d
", ans);
34 }
35 int main()
36 {
37     __int64 a, b, c;
38     while(~scanf("%I64d%I64d%I64d", &a, &b, &c))
39     {
40         while(a<0) a+=c;
41         while(b<0) b+=c;
42         Liner_modu(a, b, c);
43     }
44     return 0;
45 }
原文地址:https://www.cnblogs.com/khan724/p/4149480.html