您的位置:首页 > 其它

POJ 1061 青蛙的约会

2016-07-15 16:59 330 查看
解题报告:首先设一个k为两只青蛙跳的次数,那么k即为本题所求的变量。

那么等式(x+k*m)mod L=(y+k*n)mod L成立;

通过变形,变成(x+k*m)-(y+k*n)=p*L(p为一个整数)(该式的意思是,两只青蛙相减的路程为纬度L的整数倍,因为由上式可知,左右两边相减为0,那么他们的余数一定相等,被取余掉的部分都为L的整数倍,相减之后仍然是L的整数倍);

再通过变形,成为k*(m-n)+p*L=y-x;

再与逆元的标准式a*x+b*y=1比较,发现这个式子可以改为k*a+p*L=d;(a=m-n,d=y-x)

此时再设k‘*a+p’*L=gcd(a,L)=d',那么d‘为a,L的最大公约数;

如果b/d'为整数,则k有解,k=k'*(b/d');

如果不能整除,那么k无解。

以上是我的解题思路。但是此题感觉没用到逆元,就普通欧几里德扩展法就能出解,有点疑惑,至今还没弄清楚逆元到底是个什么。。。。

想了想发现,其实逆元是等式右边为1,那么逆元就是a*x+b*y=d的一个特例,这个特例d=1。

下面贴上代码#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
void gcd(LL a,LL b,LL &d,LL &x,LL &y)
{
if(!b) {d=a;x=1;y=0;}
else {gcd(b,a%b,d,y,x); y-=x*(a/b);}
}
LL gcd_e(LL a,LL b,LL c)
{
LL p,l,d;
gcd(a,b,d,p,l);
if(c%d!=0) return -1;
p*=c/d;
b/=d;
if(b<0) b=-b;
LL ans=p%b;
if(ans<=0) ans+=b;
return ans;
}
int main()
{
LL x,y,m,n,l;
scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);
LL ans=gcd_e(m-n,l,y-x);
if(ans==-1) printf("Impossible\n");
else printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: