欧几里得算法和扩展欧几里得算法

提示:最基本的欧几里得求最大公因数和拓展欧几里得求同余方程解以及逆元…

前言

本文主要介绍欧几里得算法求最大公因数以及拓展欧几里得算法求同余方程的解和逆元。

注:这是很早学的内容,很基础的内容,但是今天做题遇到没学出来,水一篇长长记性(* ̄(oo) ̄)


一、欧几里得算法(求两个数的最大公因数)

辗转相除法(欧几里得算法)
辗转相除法主要是求两个数的最大公因数,即gcd(a,b),举个例子大家就明白了!
例如求gcd(210,715):
在这里插入图片描述
可以看到,当余数为0时,我们就可以得到答案,所以gcd(210,715)=5。

二、拓展欧几里得求同余方程的解

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

1、贝祖定理

贝祖定理:如果a,b都为整数,那么一定存在x,y(也均为整数)使得
ax+by=gcd(a,b)。
其实就是使得方程ax+by=m有解,其中m一定是gcd(a,b)的整数倍,即m%gcd(a,b)=0。
证明如下(感觉不是很重要 ) :
由于gcd(a,b)是a和b的最大公约数,那么a%gcd(a,b)=0,同理b%gcd(a,b)=0,
又因为x,y均为整数,所以ax+by就是gcd(a,b)的整数倍,这里m=ax+by,所以m就是gcd(a,b)的整数倍,所以m%gcd(a,b)=0。

用途1:可以用贝祖定理判断一个上述样式的方程有没有解;
用途2:如果ax+by=1这个方程有解,那么a与b互素(gcd(a,b)=1)。

2、求同余方程的解

对于上面的式子ax+by=m来说,我们并不仅仅想要知道有没有解,而是想要知道在有解的情况下这个解到底是多少。
所以我们就要用到->拓展欧几里得
上面链接我觉得讲的特别好o( ̄▽ ̄)d具体解的过程大家可以看链接

接下来说一下什么是同余方程,ax≡1(modb)这就是一个同余方程,它的意思是求满足ax%b=1,1%b=1最小正整数解

代码如下:

void ex_gcd(int a, int b, int&x, int &y)//注意&
{
	if(b==0)//递归的出口
	{
		x=1;
		y=0;
		return;
	}
	int t;
	ex_gcd(b,a%b,x,y);
	t=x;
	x=y;
	y=t-(a/b)*y;
}

主义上面的x,y在主函数里定义,传的时候必须有&,没有的话在ex_gcd时x,y的值不会被修改,最后的答案就是x。
注意:!!!这里的x可能为负数,所以在输出时候应该转化为最小正整数!!!

同余方程试手点这里!!

全部代码:

#include<bits/stdc++.h>
using namespace std;

void ex_gcd(int a, int b, int&x, int &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return;
	}
	int t;
	ex_gcd(b,a%b,x,y);
	t=x;
	x=y;
	y=t-(a/b)*y;
}

int main()
{
	int a,b,x,y;
	cin>>a>>b;
	ex_gcd(a,b,x,y);
	cout<<(x+b)%b<<endl;//取正
	return 0; 
}

二、扩展欧几里得求逆元

逆元:对于同余方程ax≡1(modb),我们把x叫作a在模b下的逆,也就是逆元。可以记作a^(-1)。
用途:比如我们在计算(a/b})%c时,取模运算对除法没有分配率(先取模不能保证余数可以整除),所以我们就可以先求出b的逆元,这样原式就变成了(b^(-1)*a)%c,可以用分配率。

题目在这里

题目大意:求
f ( n ) = 1 2 + 2 2 + 3 2 + . . . . . . . + n 2 f(n)=1^2+2^2+3^2+.......+n^2 f(n)=12+22+32+.......+n2
结果对1007取余。

这个大家都学过:
f ( n ) = ( 1 / 6 ∗ n ∗ ( n + 1 ) ∗ ( n + 2 ) ) f(n)=(1/6*n*(n+1)*(n+2)) f(n)=(1/6n(n+1)(n+2))
主要处理1/6如何对1007取余就可以了,因为处理掉1/6后就可以用分配率了,所以
逆元!!!

代码如下:

#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
void ex_gcd(LL a, LL b, LL &x, LL &y)
{
    if(b==0)
    {
	x=1;
	y=0;
	return;
	}
    ex_gcd(b, a%b, x, y);
    int t;
    t=x;
    x =y;
    y = t-(a/b)*y;
}
int main()
{
    LL a,b,x,y,n,ans;
    ex_gcd(6,1007,x,y);
    x=(x+1007)%1007;
    while(cin>>n)
    {
       ans=(n*(n+1))%1007;
       ans=(ans*(2*n+1))%1007;
       ans=(ans*x)%1007;//取正 
       cout<<ans<<endl;
    }
    return 0;
}

完结撒花✿✿ヽ(°▽°)ノ✿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值