欧几里得和扩展欧几里得

(Euclid)》》》欧几里得以及扩展欧几里得

GCD

这个辗转相除的 套路:
1. int 和long long 适用的gcd

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

2. 对double 和float这些浮点数的gcd

#include <cmath>

const double eps = 1e-2;

double fgcd(double a, double b)
{
    if (fabs(a) < eps) {
        return b;
    }
    if (fabs(b) < eps) {
        return a;
    }
    return fgcd(b, fmod(a, b));
}

然后列出一些需要具备的知识:
因为:这里写图片描述
可以得到以下这几个性质:
(1)能被2整除的数,个位上的数都能被2整除
(2)能被4整除的数,个位和十位所组成的两位数能被4整除
(3)能被8整除的数,百位、十位和个位所组成的三位数能被8整除
(4)能被5整除的数,末尾是0或5
(5)能被25整除的数,十位和个位所组成的两位数能被25整除
(6)能被125整除的数,百位、十位和个位所组成的三位数能被125整除
对(1)来说,因为10,100,1000…,可以被2整除,所以就看个位了,
对(2)来说,因为100,1000,…..可以被4整除,所以就得看后两位组成的数了。
接下来的就是一些常识了:
(7)能被3整除的数,各个数位上的数字之和能被3整除
(8)能被9整除的数,各个数位上的数字和能被 9 整除
(9)如果一个数既能被 2 整除又能被 3 整除,那么这个数能被 6 整除
(10)如果一个数既能被 2 整除又能被 5 整除,那么这个数能被 10 整除(即个位为0)
(11)能被 11 整除的数,奇数位(从左往右数)上的数字和与偶数位上的数字和的差(大数减小数)能被 11 整除

Extended_GCD

就是一个方程满足 ax+by=gcd(a,b)才有解,
实现的模板就是:

LL Ext_Gcd(LL a, LL b, LL &x, LL &y);

int main()
{
    LL a, b;

    while (cin>>a>>b) {
        Ext_Gcd(a, b, x, y);
    }
    return 0;
}

其中这个函数返回的是gcd(a,b)的值,同时这个函数对求出了x,y的值。
当方程ax+by=c的左边不是gcd(a,b)的时候,
则有两种情况:
1. c不是gcd(a,b)的倍数,即c%gcd(a,b) !=0,那么方程没有解,
2. c%gcd(a,c) ==0 ,方程有解,先对方程的各个参数进行化简,得到 a’x+b’y=c’;
这样的再调用extern_gcd(a’,b’,x,y)不过得到的x只是x0,y只是y0,


**x和y的通式是


x = c * x0 +b *k (k = 0,1, 2, 3,4 ,5, 6, 7, 8 ….)
y= c * y0 - a*k k的意思同上**

不过输出的时候要保证x或者y 是正的,根据题意吧,进行一些小操作就行了。

还有一些需要掌握的知识:

POJ1061青蛙的约会

我的:
这个题呢,就是要找到这个方程,A的起点是s1,速度m,B的起点是s2,速度n,这个就相当于圆轨道,轨道的长度为L,相遇的时候满足关系式 (s1 + m*t ) % L ≡(s2 +n * t) ;即是(s1 + m*t ) % L == (s2 +n * t) % L,然后左右相减,就是整数倍个L,表达式为: (n-m) * t +L * y = s1-s2;这个时候n-m就相当于a,t相当于x,L 就相当于b,s1-s2就相当于c;
之后就按照步骤解决这个问题:
我的:

//#include<bits/stdc++.h>
#include<cmath>
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
ll x,y;

ll extended_gcd(ll a,ll b,ll &x, ll &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    ll d = extended_gcd(b,a%b, x,y);
    ll t=x;
     x=y;
    y= t- a/b*y;
    return d;
}

ll gcd(ll a, ll b)
{
    if(b==0)
    return a;
    return gcd(b,a%b);
}
int main()
{
    ll s1,s2,n,m,l;
    while(scanf("%I64d%I64d%I64d%I64d%I64d",&s1,&s2,&m,&n,&l) != EOF)
    {
       ll temp = gcd( n-m , l);
       if((s1 - s2)%temp)
       {
           cout<<"Impossible"<<endl;
           continue;
       }
       ll a=(n-m)/temp;
       ll b=l/temp;
       ll c=(s1-s2)/temp;
       extended_gcd(a,b,x,y);//得到x0=1,利用x=c*x0+b*k,k是整数;//这个函数返回的值是gcd(a,b);
//      cout<<x<<" "<<y<<endl;
      cout<<((c*x)%b+b)%b<<endl;//这里要使得结果为正,所以要进行如此的操作,使得x=c*x0+b*k为正
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值