POJ - 1061 青蛙的约会 扩展欧几里得 + (贝祖公式)最小正整数解

本文探讨了两个按相同方向跳跃的青蛙如何在有限的步数内相遇的问题,利用追击问题模型和贝祖公式进行分析,通过扩展欧几里得算法求解最小正整数解,提供了一种有效的数学解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:
青蛙 A 和 青蛙 B ,在同一纬度按照相同方向跳跃相同步数,A的起点为X ,每一步距离为m,B的起点为Y,每一步距离为 n,一圈的长度为L,求最小跳跃步数。
思路:
一开始按照追击问题来写,结果发现会求出来小数,而且按照追击问题写的话,一圈就能相遇,但是!青蛙的步数可没有小数,而且青蛙是跳跃的,显然不能在空中相遇吧。
所以咧,先列出一个追击的式子 ,设步数为 t ,整数为K(转了K圈以后他们才到同一个地方)
t * m + x = t * n + y + k * L ===> t * ( n - m ) + k * L = x - y
贝祖公式 a * x +b * y = gcd ( a , b )
当 a * x +b * y = W 时,W % gcd(a,b) = = 0
x 的最小正整数解就是要求的答案
再看扩展欧几里得

long long exgcd(long long a,long long b)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    long long r=exgcd(b,a%b);
    long long temp=x;
    x=y;
    y=(temp-a/b*y);
    return r;
}

在求a , b 的最大公约数的时候 a % b = a - (a / b) * b
a * x + b * y =gcd(a,b) ==> b * x1 + a%b * y1 = gcd( a , b )
展开得 :a * y1 +b[ x1 - ( a / b) * y1 ] = gcd( a , b )
可得 x = y1 , y= [ x1 - ( a / b) * y1 ] ;
当余数为也就是b 为 0,返回值 为 a,根据 a * x + b * y =gcd(a,b),x=1,y=0,在通过递归的回溯,计算上一个状态的 x 和 y。
最后求得的 x 可能是负数那就要找最小正整数解。
当一组解为(x, y ),那么通解公式就是 (x+b/gcd , y + a/gcd)
b/gcd 为整数的时候,它是x的解的一个周期,根据这个周期找到第一个正整数。

            long long t=l/k;//根据通解公式 (x1,y1)为一组通解,则(x1+b/gcd*k,y1+a/gcd*k)也是解
           if(t<0)//x的解得周期为b/gcd  y的解的周期 a/gcd  则任意解 x 对b/gcd取模,得出最小解,取正就ok了
                t=-1*t;
            printf("%lld\n",(x%t+t)%t);//取模运算 带入数字,x=-5,t=3,去理解

看代码:

long long x;long long y;
long long exgcd(long long a,long long b)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    long long r=exgcd(b,a%b);
    long long temp=x;
    x=y;
    y=(temp-a/b*y);
    return r;
}
int main()
{
    long long n,m,l,a,b;
    while(~scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l))
    {
        b=m-n;
        a=y-x;
        long long k=exgcd(b,l);
        if(a%k)
            printf("Impossible\n");
        else
        {
            x=x*a/k;
            long long t=l/k;//根据通解公式 (x1,y1)为一组通解,则(x1+b/gcd*k,y1+a/gcd*k)也是解
           if(t<0)//x的解得周期为b/gcd  y的解的周期 a/gcd  则任意解 x 对b/gcd取模,得出最小解,取正就ok了
                t=-1*t;
            printf("%lld\n",(x%t+t)%t);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值