zoukankan      html  css  js  c++  java
  • (扩展)欧几里德&&快速幂

    GCD模板

    __int64 gcd(__int64 a,__int64  b)
    {
        return b==0? a:gcd(b,a%b);
    }

     欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理:

      gcd函数就是用来求(a,b)的最大公约数的。

      gcd函数的基本性质:

      gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|)

    证明:

    基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%b)。

    第一种证明:

          a可以表示成a = kb + r,则r = a mod b

      假设d是a,b的一个公约数,则有

      d|a, d|b,而r = a - kb,因此d|r

      因此d是(b,a mod b)的公约数

      假设d 是(b,a mod b)的公约数,则

      d | b , d |r ,但是a = kb +r

      因此d也是(a,b)的公约数

      因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证。

    第二种证法:

    第二种证明:

        要证欧几里德算法成立,即证: gcd(a,b)=gcd(b,r),其中 gcd是取最大公约数的意思,r=a mod b
        下面证 gcd(a,b)=gcd(b,r)
        设  c是a,b的最大公约数,即c=gcd(a,b),则有 a=mc,b=nc,其中m,n为正整数,且m,n互为质数
        由 r= a mod b可知,r= a- qb 其中,q是正整数,
        则 r=a-qb=mc-qnc=(m-qn)c
        b=nc,r=(m-qn)c,且n,(m-qn)互质(假设n,m-qn不互质,则n=xd, m-qn=yd 其中x,y,d都是正整数,且d>1
                                                                    则a=mc=(qx+y)dc, b=xdc,这时a,b 的最大公约数变成dc,与前提矛盾,
                                                                     所以n ,m-qn一定互质)
        则gcd(b,r)=c=gcd(a,b)
        得证。

    扩展欧几里德定理

      对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整

      数对 x,y ,使得 gcd(a,b)=ax+by。

    证明:

    基本算法:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。

    证明:设 a>b。

      1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;

      2,ab!=0 时

      设 ax1+by1=gcd(a,b);

      bx2+(a mod b)y2=gcd(b,a mod b);

      根据朴素的欧几里德原理有 gcd(a,b)=gcd(b,a mod b);

      则:ax1+by1=bx2+(a mod b)y2;

      即:ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;

      根据恒等定理得:x1=y2; y1=x2-(a/b)*y2;

         这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.

       上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。

    以上来自 这篇博客 具体应用可以继续看这篇文章

    模板

    int exgcd(int a,int b,int &x,int &y)
    {
        if(b == 0)
        {
            x = 1; y = 0; return a;
        }
        int d = exgcd(b, a % b,x,y);
        int temp = x;
        x = y;
        y = temp - a / b * y;
        return d;
    }

     快速幂取模

    http://blog.csdn.net/hkdgjqr/article/details/5381292

    快速幂取模就是在O(logn)内求出a^n mod b的值。算法的原理是ab mod c=(a mod c)(b mod c)mod c

    二分递归

    long exp_mod(long a,long n,long b)
    {
        long t;
        if(n==0) return 1%b;
        if(n==1) return a%b;
        t=exp_mod(a,n/2,b);
        t=t*t%b;
        if((n&1)==1) t=t*a%b;
        return t;
    }

    基于二进制

    LL q_mod(LL a,LL b)
    {
    LL d,t;
    d = 1,t=a;
    while(b)
    {
    if(b&1) d = (d*t)%mod;
    b/=2;
    t = (t*t)%mod;
    }
    return d;
    }

     http://acm.hdu.edu.cn/showproblem.php?pid=2817

    View Code
     1 #include<stdio.h>
     2 #define N 200907
     3 __int64 exp_mod(__int64 a,__int64 b)
     4 {
     5     __int64 d,t;
     6     d = 1;
     7     t = a;
     8     while(b>0)
     9     {
    10         if(b%2==1)
    11             d = d*t%N;
    12         b=b/2;
    13         t = t*t%N;
    14     }
    15     return d;
    16 }
    17 int main()
    18 {
    19     __int64 n,m,a1,a2,a3,d,s,x;
    20     int i,j,k,t;
    21     scanf("%d", &t);
    22     while(t--)
    23     {
    24         scanf("%I64d%I64d%I64d%d",&a1,&a2,&a3,&k);
    25         if(a2-a1==a3-a2)
    26         {
    27             d = a3-a2;
    28             s = (a1%N+d*(k-1)%N)%N;
    29             printf("%I64d\n",s);
    30         }
    31         else
    32         {
    33             x = a3/a2;
    34             printf("%I64d\n",(a1*exp_mod(x,k-1))%N);
    35         }
    36     }
    37     return 0;
    38 }
  • 相关阅读:
    2429: [HAOI2006]聪明的猴子
    1789: [Ahoi2008]Necklace Y型项链
    3399: [Usaco2009 Mar]Sand Castle城堡
    3713: [PA2014]Iloczyn
    1907: 树的路径覆盖
    2751: [HAOI2012]容易题(easy)
    算法模板——计算几何2(二维凸包——Andrew算法)
    算法模板——splay区间反转 2
    算法模板——Dinic网络最大流 2
    算法模板——Dinic最小费用最大流
  • 原文地址:https://www.cnblogs.com/shangyu/p/2620595.html
Copyright © 2011-2022 走看看