• hiho一下 第九十五周 数论四·扩展欧几里德


    题目 : 数论四·扩展欧几里德

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    小Hi和小Ho周末在公园溜达。公园有一堆围成环形的石板,小Hi和小Ho分别站在不同的石板上。已知石板总共有m块,编号为 0..m-1,小Hi一开始站在s1号石板上,小Ho一开始站在s2号石板上。

    小Hi:小Ho,你说我们俩如果从现在开始按照固定的间隔数同时同向移动,我们会不会在某个时间点站在同一块石板上呢?

    小Ho:我觉得可能吧,你每次移动v1块,我移动v2块,我们看能不能遇上好了。

    小Hi:好啊,那我们试试呗。

    一个小时过去了,然而小Hi和小Ho还是没有一次站在同一块石板上。

    小Ho:不行了,这样走下去不知道什么时候才汇合。小Hi,你有什么办法算算具体要多久才能汇合么?

    小Hi:让我想想啊。。

    提示:扩展欧几里德

    输入

    第1行:每行5个整数s1,s2,v1,v2,m,0≤v1,v2≤m≤1,000,000,000。0≤s1,s2<m

    中间过程可能很大,最好使用64位整型

    输出

    第1行:每行1个整数,表示解,若该组数据无解则输出-1

    样例输入
    0 1 1 2 6
    样例输出
    5

    解法:

    先确定5个参数之间关系,建设存在时间t和圈数k满足:

    s1+v1*t=s2+v2*t-k*m (v1<v2)
    (v1-v2)*t+k*m=(s2-s1)
    —————— —— ——————
    A B C

    看成Ax+By=C,求通解(x,y)使等式成立。使用扩展欧几里得算法

    上式成立的条件是,方程有解,既c为A,B最大公约数的整数倍。

    欧几里得算法:是用来求解最大公约数的一种算法,大概思路是gcd(a, b) = gcd(b , a%b),辗转相除法,这样做的好处是算法时间复杂度比枚举大大降低。logn级别。

    a%b=0则,a、b的最大公约数为b。

    a%b!=0,则gcd(a, b) = gcd(b , a%b)。

    通过递归,降低数据的规模,得到一个解。

    而扩展欧几里得算法,在欧几里得算法的基础上,再求一组(x,y),ABC均为gcd(A,B)的整数倍,ABC同时缩小gcd(A,B)。

    得到A'x+B'y=C',gcd(A',B')=1,A',B'互质(A,B的最大公约数为1)

    取2组解

    A * x1 + B * y1 = gcd(A, B)
    B * x2 + (A % B) * y2 = gcd(B, A % B)

    化简为
    x1 = y2, y1 = (x2 - ky2)
    递归求解(x,y)

    终止条件为x=0,y=1;

     1 #include <iostream>
     2 typedef long long LL;
     3 using namespace std;
     4 
     5 LL gcd(LL a,LL b){
     6     if(b==0)
     7         return a;
     8     return gcd(b,a%b);
     9 }
    10 
    11 LL extend_gcd(LL a, LL b,LL &x,LL &y){
    12     if(a%b!=0){
    13         x=1;
    14         y=0;
    15         return a; 
    16     }
    17 
    18     LL ans=extend_gcd(b,a%b,x,y);
    19     LL temp=x;
    20     x=y;
    21     y=temp-(a/b)*y;
    22     return ans;
    23     
    24 }
    25 
    26 int main(){
    27     LL s1,s2,v1,v2,m;
    28     cin>>s1>>s2>>v1>>v2>>m;
    29     
    30     LL A,B,C,D,x,y;
    31      
    32     A = v1 - v2;
    33     B = m;
    34     C = s2 - s1;
    35     
    36     if (A < 0) 
    37         A = A + m ;
    38     D = gcd(A, B);
    39     
    40     if (C % D) 
    41         cout<<-1<<endl;
    42     
    43     A = A / D;
    44     B = B / D;
    45     C = C / D;
    46     
    47     x = extend_gcd(A, B,x,y);
    48     x = (x * C) % B;
    49     while (x < 0){
    50         x = x + B;
    51     } 
    52     cout<<x<<endl; 
    53 
    54 } 

     自己的机器上跑没问题,提交hiho总是WA,伤不起。有大神可以指点一二就好了。

  • 相关阅读:
    172. Factorial Trailing Zeroes
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    91. Decode Ways
    LeetCode 328 奇偶链表
    LeetCode 72 编辑距离
    LeetCode 226 翻转二叉树
    LeetCode 79单词搜索
    LeetCode 198 打家劫舍
    LeetCode 504 七进制数
  • 原文地址:https://www.cnblogs.com/SeekHit/p/5431797.html
Copyright © 2020-2023  润新知