zoukankan      html  css  js  c++  java
  • 初涉欧几里得算法系列

    昨天模拟赛A题一个类欧都没看出来我好菜啊

    先放昨天A题电阻:


     题目描述

    询问要得出一个电阻值为a/b的元件至少需要多少个电阻值为1的电阻。

    元件由3种方式组成:

    1. 一个电阻
    2. 一个元件与一个电阻串联
    3. 一个元件与一个电阻并联

    输入格式

    一行两个数, a 和 b 表示询问元件的阻值为 a/b

    输出格式

    一行一个数ans,表示最少需要的电阻数


    考试的时候先是写了一个DP打表,然后光看着表找规律了。嗯,看上去很有规律的样子然而我找规律时候完完全全地忽略了问题的性质

    DP方程是很好想的:

    于是就对着表找了一个半小时的破规律

    实际上我们可以发现,对于$f_{i,j}$,如果为$i/(i≥j)$,那么$f_{i,j}$    就是从i/j模1转移过来(串联);如果i<j,那么就是从并联转移过来的

    以下两种写法

    std:

    1 inline ll Solve(ll a,ll b){
    2   if (!a || !b) return 0;
    3   if (a>b)
    4     return Solve(a%b,b)+a/b;
    5   else
    6     return Solve(a,b%a)+b/a;
    7 }

    mine:

    #include<bits/stdc++.h>
    using namespace std;
    long long a,b;
    long long clgcd(long long a, long long b)
    {
        if (!a || !b)return 0;
        return clgcd(b%a, a)+b/a;
    }
    int main()
    {
        scanf("%lld%lld",&a,&b);
        printf("%lld
    ",clgcd(a, b));
        return 0;
    }

    嗯这就是一种简单的类欧几里得算法。


    再去找了一题exgcd的 同余方程

    题目描述

    求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解。

    输入输出格式

    输入格式:

    输入只有一行,包含两个正整数 a, b,用一个空格隔开。

    输出格式:

    输出只有一行,包含一个正整数 x0,即最小正整数解。输入数据保证一定有解。


    exgcd实际上是边在求gcd的时候边求形如ax+by=gcd(x,y)的一组整数解。

    那么为什么一定就有一组整数解满足如上条件呢?这可以由裴蜀定理得到,此处不详细展开。

     1 用类似辗转相除法,求二元一次不定方程47x+30y=1的整数解。
     2 47=30*1+17
     3 30=17*1+13
     4 17=13*1+4
     5 13=4*3+1
     6 然后把它们改写成“余数等于”的形式
     7 
     8 17=47*1+30*(-1) //式1
     9 13=30*1+17*(-1) //式2
    10 4=17*1+13*(-1) //式3
    11 1=13*1+4*(-3)
    12 然后把它们“倒回去”
    13 
    14 1=13*1+4*(-3) //应用式3
    15 1=13*1+[17*1+13*(-1)]*(-3)
    16 1=13*4+17*(-3) //应用式2
    17 1=[30*1+17*(-1)]*4+17*(-3)
    18 1=30*4+17*(-7) //应用式1
    19 1=30*4+[47*1+30*(-1)]*(-7)
    20 1=30*11+47*(-7)
    21 得解x=-7, y=11

    这里有个例子↑(源于网络)用来帮助理解扩展欧几里得算法

     1 long long exgcd(long long a, long long b, long long &x, long long &y)
     2 {
     3     if (b==0)
     4     {
     5         x = 1;
     6         y = 0;
     7         return a;
     8     }
     9     long long nx,ny;
    10     long long q = exgcd(b, a%b, nx, ny);
    11     x = ny;
    12     y = nx-a/b*ny;
    13     return q;
    14 }

    上面这个是exgcd的实现方式,也是同余方程那题的做法。

    可以看到exgcd前两个参数以及return跟gcd是一样的。至于引用的x,y两个参数,是用来递归计算同余方程根的。

    易考虑,当b==0时,方程变为ax=x,所以此时x=1;y可取任意值。为了方便起见,不如令y=0.

    至于详尽的推导过程呢,参见我找来的如下网页:

    1.扩展欧几里德算法 递归和非递归实现及证明https://blog.csdn.net/yoer77/article/details/69568676

    2.欧几里德算法https://blog.csdn.net/rentenglong2012/article/details/68944518(这篇我觉得比较详尽并且全面,不过大概是我看不懂3.之类的……)

    3.类欧几里得算法小结https://blog.csdn.net/werkeytom_ftd/article/details/53812718

    4.輾轉相除法https://www.wikiwand.com/zh/%E8%BC%BE%E8%BD%89%E7%9B%B8%E9%99%A4%E6%B3%95(实际上wiki上不去)

     事实上我也并没有非常搞懂欧几里得算法这些东西……也罢难为这篇文章标题是「初涉欧几里得算法系列」

    这一类欧几里得算法还是比较有趣的,要去花点时间去研究一下。

    不过感觉今天晚上大概有点收效甚微啊……前两个小时都在看exgcd的博客,推来推去也没有什么很大的成果。后来也就是只做了一题同余方程,然后三个半小时就这么过去了?

    大概是信竞教室旁边缺一个数竞教室?

  • 相关阅读:
    python读取xml文件报错ValueError: multi-byte encodings are not supported
    使用命令创建jenkins的job,解决jenkinsapi.custom_exceptions.JenkinsAPIException错误
    使用Python命令创建jenkins的job
    使用selenium grid分布式执行之一
    使用python 操作liunx的svn,方案二
    使用python 操作liunx的svn,方案一
    使用shell脚本实现在liunx上进行svn的上传下载更新功能
    java连接ssh执行shell脚本
    perl学习(二)正则表达式
    googletest进行单元测试(使用cmake编译)
  • 原文地址:https://www.cnblogs.com/antiquality/p/8641347.html
Copyright © 2011-2022 走看看