zoukankan      html  css  js  c++  java
  • 数学问题(一)

    1. 辗转相除法/欧几里得算法

        用辗转相除法求两个整数的最大公约数。记 gcd(a,b) 为两个数a和b的最大公约数。辗转相除法的理论依据为: gcd(a, b) = gcd(b, a % b). 
        因为设t为a和b的最大公约数,则 a = mt, b = nt, m和n互斥,a = k*b + a%b, k = a/b. 那么 mt = k*nt +a%b,于是a%b可以被t整除,则t为b和a%b的公约数,设 a%b = rt. 
        t = gcd(b, a%b) <==> n 和 r 互斥 
    由mt = k*nt + rt, 若 n和r不互斥,则设 n = ps, r = qs, s != 1,于是得到 m 可以被s整除,即 m和n不互斥,与之前的结论矛盾! 
    因此 gcd(a, b) = gcd(b, a%b)

    算法实现

    int gcd(int a, int b){
        if(b == 0)
            return a;
        return gcd(b, a % b);
    }
    

    2. 扩展辗转相除法

        整数a和b,最大公约数为gcd(a,b),一定有 ax + by = gcd(a, b)。如何求出x和y呢? 
         设 bx' + a%b*y' = gcd(b, a%b),根据欧几里得定理有bx' + a%b*y' = gcd(b, a%b) = gcd(a, b) = ax + by,则有bx' + a%b*y' = ax + by。 
    由于 a%b = a - a / b,因此 bx' + (a - a/b)y' = ax + by,即 ay' + b(x' - a/b*y') = ax + by,则有 
    x = y' 
    y = x' - a/b*y' 
    于是,可以在求得满足bx' + a%b*y' = gcd(b, a%b)的x'和y'之后再继续求出x和y,当b = 0时, x = 1, y = 0即可返回。

    算法实现

    //返回a和b的最大公约数,同时返回时的x和y满足 ax + by = gcd(a, b)
    int extgcd(int a, int b, int& x, int& y){
        if (b == 0){
            x = 1;
            y = 0;
            return a;
        }
        int d = extgcd(b, a % b, y, x);
        y -= (a/b)*x;
        return d;
    }
    

    3. 模运算

        注意在某些环境下,若a为负数,则 a%m的结果也是负数,因此若想要得到a%m在[0, m-1)范围内的值,可以使用 (m + a % m) %m。 
        a和b对m同余,可以表示为 a = b(mod m)。假设a=c(mod m), b = d(mod m),那么有以下基本规律: 
    a + b = c + d(mod m) 
    a - b = c - d(mod m) 
    a x b = c x d(mod m)

    4. 快速幂算法

        求一个整数x的n次方 xn,若n表示为2进制为n=ktkt1....k1k0(b)n=2kii1+2ki2+... 
    xn=x(2ki1+2ki2+...) = x2ki1x2ki2x2ki3... 
    于是,可以按照幂次从低到高依次计算出来x2ki,然后在n的二进制表示中若ki为1,则最后的结果需要乘以 x2ki

    long long mod_pow(long long x, long long n, long long m){
        long long res = 1;
        while(n >  0){
            if (n & 1)
                res = res * x % m;
            x = x * x % m;
            n >= 1;
        }
        return res;
    }
    

    5. 矩阵的幂

    typedef vector<int> vec;
    typedef vector<vec> mat;
    typedef long long int ll;
    const int M = 10000;
    
    //计算 A*B
    mat mul(mat& A, mat& B){
        mat C(A.size(), vec(B[0].size()));
        for(int i = 0; i < A.size(); i ++){
            for(int k = 0; k < B.size(); k ++){
                for(int j = 0; j < B[0].size(); j ++){
                    C[i][j] = (C[i][j] + A[i][k]*B[k][j]) % M;
                }
            }
        }
        return C:
    }
    //计算A^n
    mat pow(mat A, ll n){
        mat B(A.size(), vec(A.size()));
        for(int i = 0; i < A.size(); i ++){
            B[i][i] = 1;
        }
        while(n > 0){
            if (n & 1)
                B = mul(B, A);
            A = mul(A, A)
            n >= 1;
        }
        return B;
    }
    

     

  • 相关阅读:
    一步一步实现一个简单的OS(简单的让boot载入setup)
    hdu 1203 I NEED A OFFER!(01背包)
    面向服务与微服务架构
    ThreadLocal,LinkedBlockingQueue,线程池 获取数据库连接2改进
    deeplearning.net 0.1 document
    怎样有效的降低反复的代码
    redmine 自己定义字段mysql表结构
    c语言中使用宏,需要注意的的几点
    gcc自有的define语法,解决变量多次自加的问题
    ubuntu16.04 安装docker
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4901356.html
Copyright © 2011-2022 走看看