2019多校第五场 HDU6624 fraction(辗转求分数中间值)

本文探讨了求解最小正整数b的问题,使存在a<b满足a≡bx(modp),其中p,x已知且p为质数。通过将问题转化为a=bx-py的形式,并利用辗转相除法解决,提供了详细的算法实现与代码示例。

链接HDU6624 fraction

题意:

求出最小的正整数 b b b,使得存在正整数 a &lt; b a\lt b a<b,满足 a ≡ b x ( m o d p ) a\equiv bx\pmod p abx(modp)

p , x p,x p,x已知,且 p p p为质数, 1 &lt; x &lt; p ≤ 1 0 15 1\lt x\lt p\le10^{15} 1<x<p1015



分析:

和解同余方程一样,把 a ≡ b x ( m o d p ) a\equiv bx\pmod p abx(modp)转化为 a = b x − p y a=bx-py a=bxpy

由于 0 &lt; a &lt; b 0\lt a\lt b 0<a<b,即 0 &lt; b x − p y &lt; b 0\lt bx-py\lt b 0<bxpy<b,可解得:
p x &lt; b y &lt; p x − 1 \frac{p}{x}\lt \frac{b}{y}\lt \frac{p}{x-1} xp<yb<x1p

然后解最小的正整数 b b b即可,方法的话就是辗转相除法,可以看这里:传送门

(根据dls的讲解写的,可能存在纰漏,欢迎指正。)



以下代码:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL gcd(LL a,LL b)
{
    return b?gcd(b,a%b):a;
}
void solve(LL a,LL b,LL &x,LL &y,LL c,LL d)
{   
    //d==0说明c/d是正无穷,区间内肯定有整数
    if(d==0||(c%d==0?(a/b+1<c/d):(a/b+1<=c/d)))
    {                //若a/b到c/d之间有整数
        x=a/b+1;
        y=1;
        return;
    }
    LL t=a/b;
    a-=t*b;
    c-=t*d;
    solve(d,c,y,x,b,a);
    x+=t*y;
}
LL qmul(LL a,LL b,LL c)
{
    LL res=0;
    while(b)
    {
        if(b&1)
            res=(res+a)%c;
        a=(a<<1)%c;
        b>>=1;
    }
    return res;
}
LL p,x,b,y,a;
LL A,B,C,D;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld %lld",&p,&x);
        A=p/gcd(p,x),B=x/gcd(p,x);
        C=p/gcd(p,x-1),D=(x-1)/gcd(p,x-1);
        solve(A,B,b,y,C,D);
        a=qmul(b,x,p);
        printf("%lld/%lld\n",a,b);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值