POJ http://poj.org/problem?id=1061
什么是乘法逆元?
如果a与x的积除以z所得的余数为1,即 ax%z = 1 或 ax = 1(modz) ,则称a和x对于模数z来说互为逆元
记做: a^(-1) = x(mod z) 或 x^(-1) = a(mod z) 或 x ≡ 1/a(mod m) [其中1/a按指数法就写为a^(-1)].
其中如果a与z互质,则存在逆元,否则不存在
扩展欧几里德:
将公式 ax%y =1转化为 ax+by = 1;
很显然,当a和b不互质时,上式不可能成立,但一定满足贝祖等式 ax+by = gcd(a,b) = d
扩展欧几里德意义:
用来在已知a,b求解一组x,y, 使等式 ax+by = gcd(a, b) = d 成立(解一定存在)
方法:
已知 a*x1+b*y1 = gcd(a,b)
b*x2+(a%b)*y2 = gcd(b,a%b)
可得→ a*x1+b*y1 = b*x2+(a%b)*y2
→a*x1+b*y1 = b*x2+(a-a/b*b)*y2
→a*x1+b*y1 = b*x2+a*y2-a/b*b*y2
→x1 = y2 y1 = x2-a/b*y2;
当b = 0时, 显然gcd(a,b) = a。此时 x = 1,y = 0
所以只要将x和y通过上述转换递推回去即可,然后将最后得出的x1通过代入公式x = (x1%(b/gcd(a,b))+
b/gcd(a,b))%b/gcd(a,b)即可得出x
解题思路:
数据: 设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y.青蛙A一次能跳m米,青蛙B一次能跳n米.两只青蛙跳一次所
花费的时间相同.纬度线总长L米(形成环),则可得相遇充要公式: (x+m*t)-(y+n*t) = L*q; (t为跳的次数,q为跳的圈数)
将公式转化得 (n-m)*t+q*L = x-y,很显然,当x-y是gcd(n-m, L)的倍数时, 两青蛙才能相遇,此时答案便是
t*[(x-y)/gcd(n-m, L)],但x-y可能为负数,所以需要(答案%(L/gcd(n-m, L))+L/gcd(n-m, L))%(L/gcd(n-m, L))%L;
#include<stdio.h>
#define Swap(a, b) temp = a, a = b, b = temp
long long x1, y1;
long long PowerGcd(long long a, long long b);
int main(void)
{
long long x, y, n, m, p, d, temp;
while(scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &p)!=EOF)
{
if(n<m)
{
Swap(n, m);
Swap(x, y);
}
d = PowerGcd(n-m, p);
if((x-y)%d!=0)
printf("Impossible\n");
else
printf("%lld\n", ((x1*(x-y)/d)%(p/d)+p/d)%(p/d));
}
return 0;
}
long long PowerGcd(long long a, long long b) /*扩展欧几里德*/
{
long long t, temp;
if(b==0)
{
x1 = 1;
y1 = 0;
return a;
}
t = PowerGcd(b, a%b);
temp = x1;
x1 = y1;
y1 = temp-a/b*y1;
return t;
}