(Euclid)》》》欧几里得以及扩展欧几里得
这个辗转相除的 套路:
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
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 整除
就是一个方程满足 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 = 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
#include
#include
#include
#include
#include
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"<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<*x)%b+b)%b<//这里要使得结果为正,所以要进行如此的操作,使得x=c*x0+b*k为正
}
return 0;
}