ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-03-31 00:02:35  阅读:502  来源: 互联网

标签:a% gcd LL exgcd 蓝桥 return 同余 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!!!

 

标签:a%,gcd,LL,exgcd,蓝桥,return,同余,Acwing
来源: https://www.cnblogs.com/qinmo/p/16079826.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有