当年没填起来
的坑,迟早会再一次掉进去!!!想想还是将现在自己会用了的部分记录下来,以后再做补充。
欧几里得算法:
到目前为止也只是用来求一下两个整数的最大公约数(感觉又是一个巨大无比的坑)。暂时先把这个用法记下来吧。
//非递归实现
long long gcd(long long a,long long b)
{
int temp;
while(b)
{
a = a % b;
swap(a ,b);
}
return a;
}
//递归实现
long long gcd(long long a, long long b)
{
return b == 0 ? a : gcd(b, a % b);
}
扩展欧几里得算法:
同样为自己挖了一个巨大无比的坑,需要自己慢慢去填满;上代码吧还是;
//递归实现
long long exgcd(long long a,long long b,long long &x,long long &y)
{
if( b == 0)
{
x = 1;
y = 0;
return a;//最后的返回值就是a和b的最大公约数
}
long long r = exgcd(b,a%b,y,x);
y=y-a/b*x;//通过引用同时求出了线性方程的一组特殊解
return r;
}
把自己学到的细节一点一点列出来吧,可能逻辑性会差很多;
- 首先就是变量的类型,防止变量大小溢出;
- 求出的最后的x可能是负的,如果题目要求是正的可以这样处理。令, 然后 x = (*x % r + r) % r,注意如果还要求 y 的大小的话,一定要通过等式转换来重新求出y来才行;
如果是求得的 x 和 y 的解,一定要对等式左右两边同时除以c,即,然后通过扩展欧几里得求得的 x0 = x / c;
附一个扩展欧几里得的模板题(因为自己刚刚学的扩展欧几里得算法,不太透彻,这个题卡了好久,太渣了。。。。。。)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
LL x, y;
LL exgcd(LL a, LL b, LL&x, LL &y)
{
LL d;
if(b == 0)
{
x = 1;
y = 0;
return a;
}
else
d = exgcd(b, a % b, y, x);
y -= x * (a / b);
return d;
}
int main()
{
LL a,b;
while(scanf("%lld%lld",&a,&b) != EOF)
{
if(exgcd(a,b,x,y) != 1)printf("sorry\n");
else
{
x = (x % b + b) % b;
y = (1 - a * x) / b;//就是这里卡的我一愣一愣的......
printf("%lld %lld\n",x, y);
}
}
return 0;
}