您的位置:首页 > 其它

POJ 1061 青蛙的约会

2014-03-20 14:35 127 查看
题目大意:中文

题目链接

注释代码:

//引入概念——求解线性不定方程
//求解线性不定方程ax + by = c
//求a、b的最大公约数(Greatest Common Divisor,简称GCD)即d = gcd(a, b),算法为辗转相除法(即欧几里得算法)
//若d能整除c(即c mod d = 0)则表示方程有解,否则误解
//若有解则利用扩展欧几里得算法求解方程的根,步骤为:
//先将方程两边同除以d得到 _ax + _by = _c
//求出该方程的唯一解xx和yy
//最后得到整个线性方程的全解(即解集)
//x = _c * xx + t * _b
//y = _c * yy - t * _a
//t为任意整数

/*
* Problem ID : POJ 1061 青蛙的约会
* Author     : Lirx.t.Una
* Language   : C++
* Run Time   : 0 ms
* Run Memory : 172 KB
*/

#include <stdio.h>

typedef	long long	llg;

llg
gcd( llg a, llg b ) {//辗转相除法

if ( !b )
return a;

//递归算法
//return gcd( b, a % b );

llg		t;

//非递归算法
while ( b )	{

t = b;
b = a % b;
a = t;
}

return a;
}

void
xuclid( llg a, llg b, llg &x, llg &y ) {//extend Euclid
//扩展欧几里得算法

if ( !b ) {

x = 1;
y = 0;

return ;
}

llg		t;

xuclid( b, a % b, x, y );//得到bx + ( a % b )y = c的解

//计算公式
t = x;
x = y;
y = t - a / b * y;
}

int
main() {

llg		x, y, m, n, l;//两青蛙的起始位置、速度、维度线长
llg		a, b, c;//方程系数
llg		s, k;//step,步数,绕维度线的圈数
llg		d;//最大公约数
llg		t;//temporary,临时变量

scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &l);

//待解的线性不定方程为:
//(x + m * s) - (y + n * s) = k * l (k为整数)
//化简后得:
//(n - m) * s + k * l = x - y
//令
a = n - m;
b = l;
c = x - y;
//之后按照公式计算解即可

d = gcd( a, b );

if ( c % d ) {

puts("Impossible");
return 0;
}

a /= d;
b /= d;
c /= d;

xuclid( a, b, s, k );

//由于解必须是正整数,且为最小值,因此需要对解进行修正
t = c * s / b;//使t * b和c * s最接近
s = c * s - t * b;

//由于b = l必定大于0,因此可以直接相加,不必考虑b小于0的情况
if ( s < 0 )
s += b;

printf("%lld\n", s);

return 0;
}


无注释代码:

#include <stdio.h>

typedef	long long	llg;

llg
gcd( llg a, llg b ) {

if ( !b )
return a;

llg		t;

while ( b )	{

t = b;
b = a % b;
a = t;
}

return a;
}

void
xuclid( llg a, llg b, llg &x, llg &y ) {

if ( !b ) {

x = 1;
y = 0;

return ;
}

llg		t;

xuclid( b, a % b, x, y );

t = x;
x = y;
y = t - a / b * y;
}

int
main() {

llg		x, y, m, n, l;
llg		a, b, c;
llg		s, k;
llg		d;
llg		t;

scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &l);

a = n - m;
b = l;
c = x - y;

d = gcd( a, b );

if ( c % d ) {

puts("Impossible");
return 0;
}

a /= d;
b /= d;
c /= d;

xuclid( a, b, s, k );

t = c * s / b;
s = c * s - t * b;

if ( s < 0 )
s += b;

printf("%lld\n", s);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: