Description
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。
Input
输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。
Output
输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible"
Sample Input
1 2 3 4 5
Sample Output
4
题意:大体就是A在x处开始跳,每次跳m,b在y处开始,每次跳n问两个能否相遇,路径总长度为L,是循环的一个环。
思路:数论题,用到的是扩展欧几里得,好吧是我太菜了一直没搞懂这个算法。
首先可以得出一个方程[x+k*m](mod L)≡[y+k*n](mod L),可以转化为(n-m) * k ≡ x-y (mod L),
进而得到(m-n)*k+s*L=y-x(好吧这个转换不会,从大佬那抄来的),
现在已经符合ax+by=c的方程了,设a=m-n,b=L,c=y-x,然后套用模板求出特解k的值,注意k>0,所以要用通解公式得出最小正整数。
用到三个定理:
1 gcd(a,b)是ax+by的线性组合的最小正整数,x,y∈z;如果d = gcd(a, b),则必能找到正的或负的整数k和l,使d = a*k + b*l
2 如果ax+by=c,x,y∈z;则c%gcd(a,b)==0;若gcd(a, b)=1,则方程ax ≡ c (mod b)在[0, b-1]上有唯一解。
3 如果是互质的正整数,是整数,且方程ax+by=c,有一组整数解x0,y0则此方程的一切整数解可以表示为x=x0+bt;y=y0-at;t∈z;
用扩展的欧几里德求出其中一组解t0 ,p0, 并令d = gcd(a, b),有 a * t0 + b * p0 = d; (2)
(2)式两边都乘(c/ d) 得 a * t0 *(c / d) + b * p0 * (c / d) = d* (c/d)=d;
因为d = gcd(a, b), 所以 a * t0/ d是整数,b * p0 / d 也是整数,所以 c/ d 也需要是整数,否则无解。
所以t0 * (c / d)是最小的解,但有可能是负数。
因为a * ( t0 *(c / d) + b*n) + b * (p0 * (c / d) – a*n) = c; (n是自然数),所以解为 (t0 * (c / d) % b + b)%b。
关于扩展欧几里得:
对于不完全为0的非负整数a, b gcd(a, b)表示a, b 的最大公约数。那么存在整数x, y使得 gcd(a, b) = a * x + b * y;
不妨设a > b
①,当b = 0 时,gcd(a, b) = a , 此时 x = 1, y = 0;
②,当 a * b 大于或小于 0 时,
设 a * x + b * y = gcd(a, b); (1)
b * x0 + (a % b) * y0 = gcd( b, a % b); (2)
由欧几里德公式: gcd(a, b) = gcd (b, a % b);得(1),(2)
a * x + b * y = b * x0 + (a % b) * y0
= b * x0 + (a – a / b * b) * y0
= a * y0 + ( x0 – a / b * y0 ) * b
所以 x = y0, y = x0 – a / b * y0;
由此可以得出扩展欧几里德算法。
代码:
1 #include