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


    题目

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

    分析

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

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

    $ecause 0 < a=bx-pt < b$

    $ herefore frac{p}{x} < frac{b}{t} < frac{p}{x-1}$

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

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

    若 $left lfloor frac{a}{b} ight floor eq left lfloor frac{c}{d} ight floor$,直接取 $x = left lfloor frac{a}{b} ight floor, y = 1$;

    若 $left lfloor frac{a}{b} ight floor =  left lfloor frac{c}{d} ight floor$,先统一减去整数部分,然后取倒数,即 $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
    ", a, b);
        }
        return 0;
    }

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

  • 相关阅读:
    java中并发包简要分析01
    java中的集合包简要分析
    多线程学习——终结任务
    大型高并发高负载网站的系统架构
    An expression evaluator
    java公式解析器学习与开发(2)——前缀表达式
    java公式解析器学习与开发(1)
    程序员遇到bug时常见的30种反应
    图论--SCC强连通缩点--Tarjan
    图论--割边--Tarjan模板
  • 原文地址:https://www.cnblogs.com/lfri/p/11309836.html
Copyright © 2020-2023  润新知