[算法] 数学问题

  1. <cmath>中常用函数
    pow(base, exponent)
    sqrt(x)
    fmax、fmin、fabs
    ceil、floor、round(四舍五入)
    上述这些返回值和参数默认都是浮点数 注意强制类型转换 注意double强制转int 向下舍入
    e.x. %的除数和被除数都必须为整型变量且除数不能为0否则runtime error
    abs的返回值虽然是整型,但它同时为整型和浮点型重载,可替代fabs
    fmin、fmax是<cmath>中求最值的方法,不过我们通常使用algorithm头文件中的min 、max,后者还可以自定义比较函数

  2. 模运算

  • 负数取模
    e.x. 日期与当前日期的天数差值可能为负
    (days % 7 + 7) % 7
    加上求模的除数仍要再取一次模,保证原来模为0的情况仍为0

  • 大数求模
    (a*b) % c = (a % c * b % c) % c
    (a+b) % c = (a % c + b % c ) % c

  1. GCD & LCM
    最大公约数 Greatest Common Divisor
    欧几里得算法 辗转相除
while( b!= 0) {
int t = a % b;
a = b;
b = t;
}
return a;

最小公倍数 Least Common Multiple
a * b / gcd(a,b)

  1. 素数
  • 素数判定
bool isPrime(int x) {
    if (x <= 1)
        return false;
    for(int i = 2; i*i <= x; i++) {
        if (x % i == 0) {
            return false;
        }
    }
    return true;
}
  • 素数筛法
    Sieve of Eratosthenes 排除法
    O(n*log(log(n)))
bool prime[n+1]; 
    memset(prime, true, sizeof(prime)); 
 
    for (int p=2; p*p<=n; p++) 
    { 
        if (prime[p] == true) 
        { 
             // less than p^2 are already been marked.  
            for (int i=p*p; i<=n; i += p) 
                prime[i] = false; 
        } 
    } 

Sieve of Euler 欧拉筛法
O(n)

  1. 分解质因数
  2. 数位拆解
    do{
    } while(a != 0);
    可避免数本身为0时未分解到任何结果的情况
  3. 进制转换
  • 注意字符与数字比较时一定记得加单引号'0'
  • 注意向字符串转换和从字符串转换时的反序和反向遍历操作
  • 注意处理0和负数
    从字符串转换时判断s[0] == '-' ,向字符串转换时0和负数的构造
  1. 高精度
  • 高精度加法
vector<int> bigAdd(vector<int>& a, vector<int>& b) {
    vector<int> res;
    int alen = (int)a.size();
    int blen = (int)b.size();
    for (int i = 0, g = 0; ; i++) {
        if (g == 0 && i >= alen && i > blen) {
            break;
        }
        if (i < alen) {
            g += a[i];
        }
        if (i < blen) {
            g += b[i];
        }
        res.push_back(g % BASE);
        g /= BASE;
    }
    return res;
}
  • 高精度乘法
vector<int> bigMul(vector<int>& a, vector<int>& b) {
    int alen = (int)a.size();
    int blen = (int)b.size();
    int index;
    for (index = 0; index < a.size() && a[index] == 0; index++) {}
    if (index == a.size()) return { 0 };
    for (index = 0; index < b.size() && b[index] == 0; index++) {}
    if (index == b.size()) return { 0 };
    vector<int> res(alen + blen, 0);
    // i*j存放i+j
    for (int i = 0; i < alen; i++) {
        for (int j = 0; j < blen; j++) {
            res[i + j] += a[i] * b[j];
        }
    }
    int g = 0;
    for (int i = 0; i < (int)res.size(); i++) {
        int tmp = res[i] + g;
        res[i] = tmp % BASE;
        g = tmp / BASE;
    }
    while (res.back() == 0) {
        res.pop_back();
    }
    return res;
}
  • 高精度求模
  1. 二分求幂

快速幂

矩阵快速幂

mat qPow (mat A, ll n) {
    int len = (int)A.size();
    mat res(len, vector<BigInt>(len));
    res[0][0] = res[1][1] = 1;
    res[0][1] = res[1][0] = 0;
    while (n) {
        if ( n & 1 ) {
            res = matrixMultiply(res, A);
        }
        A = matrixMultiply(A, A);
        n >>= 1;
    }
    return res;
}

猜你喜欢

转载自blog.csdn.net/weixin_33881041/article/details/86877535