数论和线性代数

模运算

(a + b) % mod = (a % mod) + (b % mod);

(a - b) % mod = (a % mod) - (b % mod);

(a * b) % mod = (a % mod) * (b % mod);

(a / b) % mod = (a % mod) / (b % mod); 四个里面这个是不对的,比如100 / 50 在mod 2

快速幂


int pow_fast(int a, int n) {
    int ans = 1;
    while (n--) {
        if (n & 1) ans = ans * a;
        a = a * a;
        n >>= 1;
    }
    return ans;
}

矩阵快速幂

#include <bits/stdc++.h>
using namespace std;
const int N = 10;
const int INF = 0x3f;
int n;
struct matrix{ 
    int m[N][N];
    matrix() {
        memset(m, INF, sizeof m);
    }
    // int &operator[][](int i, int j){ 
    //     return m[i][j];
    // }  有没有高手能够重载[][]的,评论告诉我,我不会啊
};


matrix operator * (const matrix& a, const matrix& b) {
    // 设置一个新矩阵
    matrix c;
    // 下面的i,j,k交换位置没有关系
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            for (int k = 1; k <= n; k++) {   // i k k j
                c.m[i][j] += a.m[i][k] * b.m[k][j];
            }
        }
    }
    return c;
}

matrix pow_matrix(matrix a, int n) {
    // 定义一个单位矩阵
    matrix ans;
    for (int i = 1; i <= n; i++) {
        a.m[i][i] = 1;
    }
    // 快速幂
    while (n--) {
        if (n & 1) ans = ans * a;
        a = a * a;
        n >>= 1;
    }
    return ans;
}

矩阵的应用:

1、加速递推:(这个看看做题时候能不能想到)

斐波那契数列

计算矩阵幂的和

文字太多,自己看。

重点是S这个矩阵,利用矩阵快速幂求S的k次方,然后左下角的就是了

例6.2 Matrix power series(poj 3233)
问题描述:给定一个nXn的矩阵A和一个正整数k,求幂矩阵和 sum(k)=A小A2十A3十…十A、。
输入:第1行输入3个正整数n(n<30)、k(k<10)和m(m<10);后面n行中每行输入n个比32767小的非负整数,按行给出矩阵A的元素。输出:输出幂矩阵和sum(k),并对m 取模。

2、求两点间只经过n条边的最短路径长度

用邻接矩阵存两个点之间的权值,然后对这个矩阵求幂(公式要换一点点)

#include <bits/stdc++.h>
using namespace std;
const int N = 10;
const int INF = 0x3f;
int n;
struct matrix{ 
    int m[N][N];
    matrix() {
        memset(m, INF, sizeof m);
    }
    // int &operator[][](int i, int j){ 
    //     return m[i][j];
    // }  有没有高手能够重载[][]的,评论告诉我,我不会啊
};


matrix operator * (const matrix& a, const matrix& b) {
    // 设置一个新矩阵
    matrix c;
    // 进行乘法,因为是最短路径,所以min
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            for (int k = 1; k <= n; k++) {   // i k k j
                c.m[i][j] = min(c.m[i][j], a.m[i][k] + b.m[k][j]);
            }
        }
    }
    return c;
}

matrix pow_matrix(matrix a, int n) {
    // 定义一个单位矩阵
    matrix ans;
    for (int i = 1; i <= n; i++) {
        a.m[i][i] = 1;
    }
    // 快速幂
    while (n--) {
        if (n & 1) ans = ans * a;
        a = a * a;
        n >>= 1;
    }
    return ans;
}
int main() {
    int n, t, s, e;
    
    matrix a;
    while (t--) {
        int u, v, w; cin >> w >> u >> v;
        if(!Hash[u]) Hash[u] = ++cnt;
        if(!Hash[v]) Hash[v] = ++cnt;
        a.a[Hash[u]][Hash[v]] = a.m[Hash[v]][Hash[u]] = w;
    }
    martix ans = pow_matrix(a, n);
    printf("%d",ans.m[Hash[s]][Hash[e]]);
    return 0;
}

练习:

矩阵加速递推:洛谷p 1349 1939 1306 2044 5175    hdu 4990 4565 4965 4549 4686 5015

路径问题:hdu 2157

矩阵快速幂:洛谷 p 3390 1939 4783 1962 1349 4000 3758 4967 5343 5337 5303

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值