欧几里得算法(及扩展)&&快速幂(二分+位运算)

  最近在二中苦逼地上课,天天听数论(当然听不懂)

  但是,简单的还是懂一点的

  1.欧几里得算法

  说得这么高级干什么,gcd入门一个月的人都会吧,还需要BB?

  证明可参照其他博客(不会),主要就是gcd(a,b)=gcd(b,a%b);

  特殊的,gcd(a,0)=gcd(0,a)=a;

  然后一行

int gcd(int m,int n) { return n?gcd(n,m%n):m; }

 

  2.扩展欧几里得

  在班里天天看紫书,终于会打(背)了。

  专门对于形如 ax+by=d(a,b,d为常数,d=gcd(a,b)) 的不定方程求整数解

  证明可参照其他博客(不会),主要也是gcd(a,b)=gcd(b,a%b)(真有道理)

  

void exgcd(int a,int b,int &x,int &y)
{
    if (!b) { x=1; y=0; return; }
    int r=a%b,m=a/b;
    exgcd(b,r,y,x);
    y-=x*m;
}

 

  然后这组解满足|x|+|y|最小

  其实记代码也是可以的啦。

 

  3.快速幂

  快速幂,一个入门一个月的人都会的算法,主流有二分和快速幂两个版本。

  原理不多说,一个是把a^n拆成两个相同的部分再递归求之。一个是不停增大初始部分然后得解。

  只不过一个是二分,一个是倍增了啦。

  <1>二分

int quick_pow(int a,int n,int p) //a^n % p 
{
    if (!n) return 1;
    int res=quick_pow(a,n/2,p);
    res=(long long) (res*res)%p;
    if (a%2) res=(long long) (res*a)%p;
    return res;
}

 

  <2>位运算

int Quick_pow(int a,int n,int p) //同上 
{
    int res=1;
    while (n)
    {
        if (n&1) res=(long long) (res*a)%p;
        a=(long long) (a*a)%p;
        n=n>>1;
    }
    return res;
}

 

  篇幅还算挺大,代码都是刚刚重打的,导致我看到的一道BZOJ的巨水题没时间打了。

  至于逆元,欧拉函数什么的。。。

  一脸蒙逼。

posted @ 2017-12-14 20:22  空気力学の詩  阅读(347)  评论(1编辑  收藏  举报