首页 > 编程语言 >拓展欧几里得算法——C.一日之计在于晨

拓展欧几里得算法——C.一日之计在于晨

时间:2024-03-28 21:14:29浏览次数:17  
标签:gcd int 一日之计 欧几里得 re 算法 therefore ax mod

广州大学第十八届ACM大学生程序设计竞赛(同步赛)C题

谈到拓展欧几里得算法,就要从欧几里得算法裴蜀定理说起。

欧几里得算法(辗转相除法)

\(gcd(a,b)=gcd(b,a\mod b)\)

其中,当\(a=0\)时,\(\gcd(a,b)=\gcd(0,b)=b\);\(b=0\)同理

证明:\(gcd(a,b)=gcd(b,a-b)\)

令\(a=b+c\), \(\gcd(a,b)=d\), \(\gcd(b,c)=e\)
主要是证明\(d=e\)
\(a\mod d=0, b\mod d=0,\therefore c\mod d=0,\therefore d\leq e\)

同理,\(e\leq d,\therefore d=e\)

推广一下,相当于\(a\)不断减\(b\)直至\(a<b\),也就是直至\(a\mod b\)

int gcd(int a,int b){
	if(b==0)return a;
	return gcd(b,a%b);
}

参考:
辗转相除法的原理 _辗转相除法求最大公约数的原理是什么? (shadafang.com)

裴蜀定理(贝祖定理)

设\(a,b\)是不全为0的整数,对任意整数\(x,y\),满足\(\gcd(a,b)|ax+by\),且存在整数\(x,y\),使得\(ax+by=\gcd(a,b)\)

首先证明任意整数\(x,y\),满足\(\gcd(a,b)|ax+by\)

令\(\gcd(a,b)=d,\therefore a=k_{1}d,b=k_{2}d,(k_{1},k_{2})=1\)
\(ax+by=k_{1}dx+k_{2}dy=d(k_{1}x+k_{2}y)\)
\(\therefore \gcd(a,b)|ax+by\)

再证明存在整数\(x,y\),使得\(ax+by=\gcd(a,b)\)

设取整数 \(x_{0},y_{0}\) 时,\(ax+by\) 有最小正整数\(s\),即\(ax_{0}+by_{0}=s\)
\(\because ax_{0}\mod \gcd(a,b)=0\)
且 \(by_{0}\mod \gcd(a,b)=0\)
\(\therefore s\mod \gcd(a,b)=0\)

设\(a=qs+r,(0\leq r<s)\) ---也就是把\(a\)表示成一个整数,其中\(s\)为已知,\(q\)、\(r\)为未知数
\(\therefore r=a-qs=a-q(ax_{0}+by_{0})=a(1-qx_{0})+b(-qy_{0})=ax+by\) ---\(r\)可以表示成 \(ax+by\) 的形式
\(\because s\) 是 \(ax+by\) 的最小正整数
\(\therefore r=0\)
\(\therefore a=qs\) 即 \(a\mod s=0\)
同理,\(b\mod s=0\)
\(\therefore \gcd(a,b)\mod s=0\)

\(\because s\mod \gcd(a,b)=0,\gcd(a,b)\mod s=0,\therefore \gcd(a,b)=s\)

拓展欧几里得算法

拓展欧几里得算法实际上就是求 \(ax+by=\gcd(a,b)\) 的一组整数解

当\(b=0\)时,\(ax+by=ax=\gcd(a,0)=a\)
此时,\(x=1,y=0\) 就是 \(ax+by=\gcd(a,b)\) 的一组整数解

当\(b\neq 0\)时,
欧几里得算法可知,\(gcd(a,b)=gcd(b,a\mod b)\)
裴蜀定理可知,

\[\begin{aligned} \gcd(a,b)=ax+by \\ \gcd(b,a\mod b)=bx_{1}+(a\mod b)y_{1} \end{aligned} \]

\(\therefore x=y_{1},y=x_{1}-\frac{a}{b}y_{1}\)
利用递归,先求出下一层的\(x_{1},y_{1}\),以此类推,可以求得特解\((x_{0},y_{0})\)
构造通解

\[\begin{cases} x=x_{0}+\frac{b}{\gcd(a,b)}\ k\\ y=y_{0}-\frac{a}{\gcd(a,b)}\ k\\ \end{cases} \]

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

求\(ax+by=c\)的一组整数解

拓展欧几里得算法可知,我们可以求\(ax+by=\gcd(a,b)\)的一组整数解
那么,如果 \(c\mod gcd(a,b)=0\) ,我们只需在等式左右两边同乘\(c/\gcd(a,b)\) ,就能求得 \(ax+by=c\)的一组整数解

若\(c\mod gcd(a,b)\neq0\),则无整数解。这个可以有裴蜀定理可知,证明对于不定方程 \(ax+by=m\) 其有整数解的充要条件是 \(\gcd(a,b)|m\) 即可。

例题

广州大学第十八届ACM大学生程序设计竞赛(同步赛)C题

题目

题解

根据指针的转动,可以列出 (只是大致的,未考虑加一/减一)$$t+ax=re+my$$其中,\(x\)表示顺时针或逆时针转动的次数,\(re\) 表示指针最后停的位置,\(y\) 表示转动的圈数

移动,$$ax-my=re-t$$
我们就可以根据拓展欧几里得算法求得 \(\gcd(a,m)\),以及对应的 \((x_{0},y_{0})\)
\(re-t\) 是当\(re\)取最小值时,\(\gcd(a,m)|re-t\)
\(\because re\)的范围是\([1,m]\),所以 \(re=(t-1)\%d+1\)
这样就可以求得特解\(x=x*(re-t)/d)\)(后面还要加mod)
最后再根据通解,求出 \(x\) 的最小值。

代码

#include <bits/stdc++.h>
#define int long long
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
using namespace std;
int exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;y=0;
        return a;
    }
    int x1,y1,d;
    d=exgcd(b,a%b,x1,y1);
    x=y1;y=x1-a/b*y1;
    return d;

}
void solve(){
    int t,a,m;
    cin>>t>>a>>m;
    int x,y;
    int d=exgcd(a,m,x,y);
    t=(t-1)%d+1-t; //这里就省略了re
    x=((x*t/d)%m+m)%m; //特解
    x=(x%(m/d)+(m/d))%(m/d); //通解
    cout<<min(x,m/d-x)<<endl;
}
signed main()
{
    ios;
    int T;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

标签:gcd,int,一日之计,欧几里得,re,算法,therefore,ax,mod
From: https://www.cnblogs.com/cdag/p/18102603

相关文章

  • 设计算法判断一棵树是否为完全二叉树--c++
    【题目要求】设计算法判断一棵树是否为完全二叉树。【提示】根据完全二叉树的定义可知:1)如果一个结点有右孩子而没有左孩子,那么这棵树一定不是完全二叉树。2)如果一个结点有左孩子,而没有右孩子,那么按照层序遍历的结果,这个结点之后的所有结点都是叶子结点,这棵树才是完全二叉......
  • 高精度算法
    高精度通常,大整数的存储采用数组的形式,其中数组的首位存储大整数的最低位,末位存储最高位举例来说,对于整数123456789,我们可以使用数组存储如下:makefileCopycodeindex:012345678array:[9,8,7,6,5,4,3,2,1]这样,数组的第一......
  • 2022 Tesla AI Day -特斯拉自动驾驶FSD的进展和算法软件技术之数据以及虚拟
    2022TeslaAIDay-特斯拉自动驾驶FSD的进展和算法软件技术之数据以及虚拟附赠自动驾驶学习资料和量产经验:链接人工智能算法犹如电影的主演,我们很多时候看电影只看到主演们的精彩,但其实电影的创意和呈现都来自于背后的导演和制片等团队。而人工智能算法背后的有关数据的软件,设......
  • 每日算法之最长连续序列
    题目描述给定一个未排序的整数数组nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为O(n)的算法解决此问题。示例1:输入:nums=[100,4,200,1,3,2]输出:4解释:最长数字连续序列是[1,2,3,4]。它的长度为4。示例2:输......
  • 虚拟游戏理财 算法题
    华为ODC卷 虚拟游戏理财暴力枚举法。更好的方法是动态规划。菜鸡不会。自己也写了,但是不全对,gpt写的,但是也有问题。自己修改后正确:importjava.util.*;publicclassInvestmentGame{publicstaticvoidmain(String[]args){Scannerscanner......
  • 知识图谱推理算法综述(下):基于语义的匹配模型
    背景知识图谱系统的建设需要工程和算法的紧密配合,在工程层面,去年蚂蚁集团联合OpenKG开放知识图谱社区,共同发布了工业级知识图谱语义标准OpenSPG并开源;算法层面,蚂蚁从知识融合,知识推理,图谱应用等维度不断推进。OpenSPGGitHub,欢迎大家Star关注~:https://github.com/Ope......
  • 【算法】归并排序(递归法)
    目录归并排序简介算法步骤(递归)C语言实现归并排序简介归并排序(mergesort)是一种高效、通用且基于比较的排序算法。由约翰·冯·诺依曼(JohnvonNeumann)于1945年发明,是一种分治算法(divide-and-conqueralgorithm)。时间复杂度为O(nlog⁡n)O{\left(n\log......
  • 08天【代码随想录算法训练营34期】第四章 字符串part02(KMP)
    KMP算法解决字符串匹配问题文本串aabaabaaf模式串aabaaf问:模式串是否在文本串中出现过?1)暴力解法,ptr指向文本串index0,遍历一遍发现不匹配,ptr再移向index1,遍历……依次重复,直到ptr指向32)KMP算法,ptr指向文本串index0,遍历到f发现不匹配,由于“aa”在字符串中index3和4时也出现......
  • 数据结构与算法题目集(中文)6-1 单链表逆转 C语言
    6-1单链表逆转本题要求实现一个函数,将给定的单链表逆转。函数接口定义:ListReverse(ListL);其中List结构定义如下:typedefstructNode*PtrToNode;structNode{ElementTypeData;/*存储结点数据*/PtrToNodeNext;/*指向下一个结点的指针*/};t......
  • 最近公共祖先(lca)倍增算法【模板】
    P3379【模板】最近公共祖先(LCA)-洛谷|计算机科学教育新生态(luogu.com.cn)#include<bits/stdc++.h>#include<cstdio>usingnamespacestd;constintN=5e5+100;constintinf=0x3f3f3f;intn,m,s;vector<int>g[N];intdep[N];//存u点的深度intfa[N][20];//存从u......