2019HDU多校第五场A fraction —— 辗转相除法|类欧几里得

题目

设 $ab^{-1} = x(mod \ p)$,给出 $x,p$,要求最小的 $b$,其中 $0< a < b, \ 1 < x<p,\ 3 \leq x\leq {10}^{15}$.

分析

比赛中,首先就想用扩展欧几里得解出一个可行 $b$,然后枚举 $kb \% p$ 的最小值,然后发现复杂度爆炸。

看题解,用了一种非常巧妙地方法,

$\because 0 < a=bx-pt < b$

$\therefore \frac{p}{x} < \frac{b}{t} < \frac{p}{x-1}$

按题解,这是一个经典问题,可以用辗转相除法解决。

如,对于 $\frac{a}{b} < \frac{x}{y} < \frac{c}{d}$

若 $\left \lfloor \frac{a}{b} \right \rfloor \neq \left \lfloor \frac{c}{d} \right \rfloor$,直接取 $x = \left \lfloor \frac{a}{b} \right \rfloor, y = 1$;

若 $\left \lfloor \frac{a}{b} \right \rfloor =  \left \lfloor \frac{c}{d} \right \rfloor$,先统一减去整数部分,然后取倒数,即 $\frac{d}{c} < \frac{y}{x} < \frac{b}{a}$.

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
ll p, x;

//q求满足a/b < x/y < c/d 的最小的x和y
void f(ll a, ll b, ll c, ll d, ll& x, ll& y)
{
    ll tmp = (a+b-1)/b;
    if(tmp <= c/d)
    {
        x=tmp;
        y=1;
        return;
    }

    a -= b*(tmp-1);
    //x -= y*tmp;
    c -= d*(tmp-1);
    f(d, c, b, a, y, x);
    x += y*(tmp-1);
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lld%lld", &p, &x);
        ll b, t;
        f(p, x, p, x-1, b, t);
        ll a = b*x-p*t;
        printf("%lld/%lld\n", a, b);
    }
    return 0;
}

 

续:后来知道这种方法叫类欧几里得算法,与欧几里得相似,采用辗转相除的方法。

posted @ 2019-08-06 16:21  Rogn  阅读(321)  评论(0编辑  收藏  举报