POJ3735 Training little cats 矩阵快速幂 + 矩阵快速幂优化

有n只猫,每只猫初始石刻没糖果。 进行m次重复的k次操作。

g i 给第i只猫一个糖果

s i j  交换第i只猫和第j只猫的糖果

c i 吃掉第i只猫的所有糖果

m <=1e9 明显是用矩阵快速幂处理。 难点在于建立转移矩阵。

注意到只需对单位矩阵操作。对于n只猫建立 n+1 * 1 的矩阵,多的一行存放 1 用来转移。

g i ,即对单位矩阵 E的第i行第n + 1列 set 为1 

s i j 即对单位矩阵的i j 行交换

c i 即对单位矩阵的第i行clear

如此就可以矩阵快速幂了 。

注意到矩阵是稀疏矩阵,考虑优化。

#pragma warning(disable:4996)

#include<iostream>
#include<algorithm>
#include<bitset>
#include<tuple>
#include<unordered_map>
#include<fstream>
#include<iomanip>
#include<string>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<stack>
#include<sstream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#define INF 0x3f3f3f3f
#define inf 0x7FFFFFFF
#define MOD 998244353
#define moD 1000000003
#define pii pair<int,string>
#define eps 1e-8
#define equals(a,b) (fabs(a-b)<eps)
#define bug puts("bug")
#define re  register
#define fi first
#define se second
const int maxn = 1e6 + 5;
const double Inf = 10000.0;
const double PI = acos(-1.0);
typedef  long long ll;
typedef unsigned long long ull;
using namespace std;

struct Mat {
    ll m[105][105];
};

Mat E;
ll n, m, k;

void init(int n) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) if(i == j) E.m[i][j] = 1;
    }
}

Mat mul(const Mat& a, const Mat& b) {
    Mat c;
    for (int i = 0; i < n + 1; i++) for (int j = 0; j < n + 1; j++) c.m[i][j] = 0;
    for (int i = 0; i < n + 1; i++) {
        for (int k = 0; k < n + 1; k++) {
            if(a.m[i][k])
            for (int j = 0; j < n + 1; j++) c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j] )  ;
        }
    }
    return c;
}    

Mat mult(const Mat& a, const Mat& b) {
    Mat c;
    for (int i = 0; i < n + 1; i++) {
        for (int j = 0; j < 1; j++) {
            c.m[i][j] = 0;
            for (int k = 0; k < n + 1; k++) c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j] ) ;
        }
    }
    return c;
}

Mat ans;
Mat base;

Mat quickPower(Mat a, ll b) {
    ans = E;
    base = a;
    while (b) {
        if (b & 1) ans = mul(ans, base);
        base = mul(base, base);
        b >>= 1;
    }
    return ans;
}

Mat q;


int main() {
    init(105 + 1);
    while (scanf("%lld%lld%lld", &n, &m, &k), n || m || k) {
        Mat s;
        q = E;
        char op[3];
        int x, y;
        for (int i = 0; i < k; i++) {
            scanf("%s", op);
            if (strcmp(op, "g") == 0) {
                scanf("%d", &x);
                Mat tmp = E;
                tmp.m[x - 1][n] = 1;
                q = mul(tmp, q);
            }
            else if (strcmp(op, "s") == 0) {
                scanf("%d%d", &x, &y);
                Mat tmp = E;
                tmp.m[x - 1][x - 1] = 0;
                tmp.m[x - 1][y - 1] = 1;
                tmp.m[y - 1][y - 1] = 0;
                tmp.m[y - 1][x - 1] = 1;
                q = mul(tmp, q);
            }
            else {
                scanf("%d", &x);
                Mat  tmp = E;
                tmp.m[x - 1][x - 1] = 0;
                q = mul(tmp, q);
            }
        }
        q = quickPower(q, m);
        for (int i = 0; i < n; i++) s.m[i][0] = 0;
        s.m[n][0] = 1;
        q = mult(q, s);
        for (int i = 0; i < n; i++) printf("%lld ", q.m[i][0]);
        puts("");
    }
}
原文地址:https://www.cnblogs.com/hznumqf/p/13354670.html