zoukankan      html  css  js  c++  java
  • 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;
    }

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

  • 相关阅读:
    2019春季学期进度报告(五)
    《构建之法》读后感三
    5.4号个人冲刺(三)
    大二下学期学习进度(九)
    5.3号个人冲刺(二)
    5.2号个人冲刺(一)
    《代码大全2》阅读笔记01
    大二下学期学习进度(八)
    用户模板和用户场景
    个人作业4-用户通过单步执行的方式看到你的算法是如何工作的(之前数组)
  • 原文地址:https://www.cnblogs.com/lfri/p/11309836.html
Copyright © 2011-2022 走看看