POJ 1061 青蛙的约会

解题报告:首先设一个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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值