[Acwing蓝桥杯数学知识] 扩展欧几里得线性同余方程

2022/3/31 6:23:55

本文主要是介绍[Acwing蓝桥杯数学知识] 扩展欧几里得线性同余方程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

扩展欧几里得
用于求解方程 ax+by=gcd(a,b)的解

当 b=0时 ax+by=aax+by=a 故而 x=1,y=0x=1,y=0
当 b≠0 时因为gcd(a,b)=gcd(b,a%b)

而bx′+(a%b)y′=gcd(b,a%b)

bx′+(a−⌊a/b⌋∗b)y′=gcd(b,a%b)
ay′+b(x′−⌊a/b⌋∗y′)=gcd(b,a%b)=gcd(a,b)
故而x=y′,y=x′−⌊a/b⌋∗y′

因此可以采取递归算法 先求出下一层的x和y再利用上述公式回代即可

线性同余方程

已知 ax+by=z ( z是d的倍数 )

如果z不是d的倍数一般表示无解

这时要想用扩展欧几里得的结果

就要将等式两边同时*z/d

即x*=z/d,y*z/d;

线性同余方程一定能求出一个解(x0,y0)

且满足:

 

 

就是任意的x和y都可以用x0和y0表示出来

 

要求最小的x值就是 x0 MOD(b/d);

 

一般就是先将x扩大后 先将b除以d 然后直接MOD b就是结果

 

注意x一般要的是正数 则要取正数x=(x%b+b)%b;

 

 

 

有两个例题:1301. C 循环 - AcWing题库 ,1299. 五指山 - AcWing题库;

 

第一个题的代码:

 

 

 1 /*
 2 线性同余方程
 3 
 4 由题意得
 5 (A+C*x)mod2^k=B
 6 变形:A+C*x-2^k*y=B
 7 即 C*x-2^k*y=B-A
 8    ax+by=d
 9 
10 */
11 
12 #include <bits/stdc++.h>
13 
14 using namespace std;
15 typedef long long LL;
16 
17 LL exgcd(LL a,LL b,LL &x,LL &y)
18 {
19     if(!b)
20     {
21         x=1,y=0;
22         return a;
23     }
24     LL d=exgcd(b,a%b,y,x);
25     y-=a/b*x;
26     return d;
27 }
28 
29 int main()
30 {
31     LL a,b,c,k;
32     while(cin>>a>>b>>c>>k,a,b,c,k)
33     {
34         LL x,y;
35         k=1LL<<k;
36         LL d=exgcd(c,k,x,y);
37         if((b-a)%d)puts("FOREVER");
38         else
39         {
40             x*=(b-a)/d;
41             k/=d;
42             printf("%lld\n",(x%k+k)%k);
43         }
44     }
45     return 0;
46 }
View Code

 

第二个题的代码:

/*裴蜀定理,算法:扩展欧几里得算法
传送门https://www.acwing.com/problem/content/879/
ax+by=d
             a x   +by=exgcd
实际上应该为 n*(-x)+dy=y-x;

y-x如果不能整除exgcd那么无解

如果可以 那么两边同时除以(y-x)/exgcd

x->a y->b 求y

*/
#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    LL d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        LL a,b,x,y,d,n;
        scanf("%lld%lld%lld%lld",&n,&d,&x,&y);
        LL gcd=exgcd(n,d,a,b);
        if((y-x)%gcd)puts("Impossible");
        else
        {
            b*=(y-x)/gcd;
            n/=gcd;
            printf("%lld\n", (b % n + n) % n);
        }
    }
    return 0;
}
View Code

 

 

 

两个题都是线性同余方程的应用:

方程的转化和求解。

end!!!

 



这篇关于[Acwing蓝桥杯数学知识] 扩展欧几里得线性同余方程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程