数论----同余方程

《贝祖定理》

简单来说是: 整数 a,b ,gcd(a,b)=d;  则 存在x,y使ax+by=d成立

证明:

《扩展欧几里得算法》

好博客:https://blog.csdn.net/syz201558503103/article/details/76512144

https://blog.csdn.net/qq_44765711/article/details/102688064

 

 由贝祖定理:ax+by=gcd(a,b)

则:当不断取模gcd(a,b)=......=gcd(an,0)时

an*x+b*0=gcd,而an=gcd,所以 x=1,y=任意,为了方便y=0;

设:当前层ax+by=gcd

已知下一层的x1,y1

由下一层->这一层:

下一层的 a1=b,b1=a%b

a%b=a-(a/b)*b

即 b*x1+(a-(a/b)*b)*y1=gcd

a*y1+ b*(x1-y1*(a/b))=gcd------>x=y1,y=x1-y1*(a/b)

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 int exgcd(int a, int b, int &x, int &y)
 6 {
 7     if (!b)
 8     {
 9         x = 1, y = 0;
10         return a;
11     }
12     //这里不用担心a<b的情况,因为在下一层通过b,b%a交换了一下
13     int d = exgcd(b, a % b, x, y);
14     int t = x;
15     x = y;
16     y = t - (a / b) * y;
17     return d;
18 }
19 int main()
20 {
21     int t;
22     cin >> t;
23     while (t--)
24     {
25         int a, b, x, y;
26         scanf("%d%d", &a, &b);
27         exgcd(a, b, x, y);
28         printf("%d %d\n", x, y);
29     }
30     return 0;
31 }

 《通解》

 

 

 《ax+by=k  && gcd(a,b)|k的求解方法》

对于 ax+by=gcd(a,b)的一组特解:(x0,y1)

在这里我要重点说明一下:扩展欧几里得算法是求ax+by=gcd(a,b)的算法

而不是求ax+by=k的算法

ax+by=k && gcd(a,b)|k的一组特解为

(x0*w,y0*w),其中w=k/gcd(a,b);

证明:

代入即可:

a*x0*k/gcd(a,b)+b*y0*k/gcd(a,b)=k--------------->

a*x0+b*y0=gcd(a,b)是成立的

《对于ax+by=k的通解》

我们令 x1=x0*w,y1=y0*w;

 

 

 

 

 

 《求ax+by=k的解的个数》

 

 

 

 

 

由:

f(2)=x+y

f(3)=x+2y

f(4)=2x+3y

f(5)=3x+5y

f(6)=5x+8y

....

可以得到x与y前系数的规律:即其实个斐波那契数列:

有g(0)=1,g(1)=1

f(i)=g(i-2)*x+g(i-1)*y

我们可以预处理g(),这个斐波那契数列在g(45)时已经>1e9,而明显对于ax+by=k的求解

在x && y>0的情况下 a && b<1e9

我们可以枚举0~45的g()

然后问题变成了求g(i-1)*x+g(i)*y=k的x和y的解的个数问题

然后根据一顿操作(我上面讲了)求通解:

 

 

 这里b=g(i),a=g(i-1)

 

 

 基本思路是:

当求出的x1<=0时,让其变为最小的>0的整数解,根据通解的形式可以判断出这个时候y1是最大的y1了

然后看一下这个时候的y1最大能够减多少个a

通过y1/a,假设y1/a=n

则有解:y1,y1-a,y1-a*2......,y1-a*n

当y1%a==0时,y1-a*n是不行的,因为解要>0,

则:当y1%a==0时,解有y1/a个解,否则有y1/a+1个解

当求出y1<=0时同理

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 const ll mod = 1e9 + 7;
 7 int k;
 8 ll f[50];
 9 ll exgcd(ll a, ll b, ll &x, ll &y)
10 {
11     if (!b)
12     {
13         x = 1, y = 0;
14         return a;
15     }
16     ll gcd = exgcd(b, a % b, x, y);
17     ll t = x;
18     x = y;
19     y = t - (a / b) * y;
20     return gcd;
21 }
22 int main()
23 {
24     scanf("%d", &k);
25     f[0] = 1, f[1] = 1;
26     for (int i = 2; i <= 45; i++)
27         f[i] = f[i - 1] + f[i - 2];
28     /* 当f[44]时就已经超过1e9了
29      cout<<f[44]; */
30     //对于每一个f[i-1]x+f[i]y=k,都要看一下
31     ll ans = 0;
32     for (int i = 1; f[i] < k; i++)
33     {
34         //首先求出f[i-1]x+f[i]y=gcd(f[i-1],f[i])=1的特解x0,y0
35         ll x0, y0;
36         ll gcd = exgcd(f[i - 1], f[i], x0, y0);
37         //然后求出f[i-1]x+f[i]y=k的特解
38         //其特解为x0*k/gcd,y0*k/gcd,这里为x0*k,y0*k
39         x0 *= k, y0 *= k;
40         //因为要求x>0,y>0,如果开始求出的x0 || y0<=0,我们就要将其变为>0
41         ll t = 0;
42         if (x0 <= 0)
43         {
44             //这个操作后,x0一定会>0
45             t = -x0 / f[i] + 1;
46             x0 += f[i] * t;
47             y0 -= f[i - 1] * t;
48             //如果让x0成为最小>0后,y0<=0说明无解
49             if (y0 <= 0)
50                 continue;
51             ans += (y0 % f[i - 1] == 0) ? y0 / f[i - 1] : y0 / f[i - 1] + 1;
52             ans %= mod;
53         }
54         else if (y0 <= 0)
55         {
56             //让y0变成最小整数解
57             //则 变后: ymin=y0+(y0/f[i-1]+1)*f[i-1],xmax=x0-f[i]*(y0/f[i-1]+1);
58             t = -y0 / f[i - 1] + 1;
59             y0 += f[i - 1] * t;
60             x0 -= f[i] * t;
61             if (x0 <= 0)
62                 continue;
63             ans += (x0 % f[i] == 0) ? x0 / f[i] : x0 / f[i] + 1;
64             ans %= mod;
65         }
66     }
67     printf("%lld", ans);
68     return 0;
69 }

 

《一元线性同余方程》

 

 

 由 ax mod b =c ---> ax=y*b+c-----> ax+by=c

 

 《中国剩余定理》

 

 

 

 

 《证明》

1.首先通解形式肯定是原方程组的解(一个一个代进去会发现都成立)

2.

 

 

 

 这里说明一下为啥 x1-x2≡0(modmi)

因为

 

 

 则 x1=k1*mi+ai   ,    x2 =k2* mi+ai

x1-x2=(k1-k2)*mi---->x1-x2≡0(modmi)

 

 

posted @ 2022-08-23 00:14  次林梦叶  阅读(168)  评论(0)    收藏  举报