zoukankan      html  css  js  c++  java
  • AcWing

    https://www.acwing.com/problem/content/208/

    因为1~6的最小公倍数是60,所以以60为周期进行快速幂然后剩下的算余项,注意两点:

    1、递推矩阵永远有这样的形式:

    A=A*B

    其中A就是用来把各步的递推结果压缩保存的矩阵(仿照快速幂)

    2、越界的石子直接消失了,原题没说明要怎么处理
    3、计算的过程会溢出

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int mod = 10000007;
    struct Matrix {
        static const int MAXN = 65;
        ll ma[MAXN][MAXN];
        Matrix() {
            //init();
        }
        void init() {
            memset(ma, 0, sizeof(ma));
        }
        void setE() {
            init();
            for(int i = 0; i < MAXN; ++i)
                ma[i][i] = 1;
        }
    
        Matrix operator+(const Matrix &m)const {
            Matrix Tmp;
            Tmp.init();
            for(int i = 0; i < MAXN; ++i) {
                for(int j = 0; j < MAXN; ++j)
                    Tmp.ma[i][j] = ma[i][j] + m.ma[i][j];
            }
            return Tmp;
        }
    
        Matrix operator*(const Matrix &m)const {
            Matrix Tmp;
            Tmp.init();
            for(int k = 0; k < MAXN; ++k) {
                for(int i = 0; i < MAXN; ++i) {
                    register ll r = ma[i][k];
                    for(int j = 0; j < MAXN; ++j)
                        Tmp.ma[i][j] += r * m.ma[k][j];
                }
            }
            return Tmp;
        }
    
        void show(int n) {
            for(int i = 0; i < n; ++i) {
                for(int j = 0; j < n; ++j) {
                    printf("%2d ", ma[i][j]);
                }
                puts("");
            }
            puts("---");
        }
    } tma[60], Tma, F;
    
    Matrix qpow(Matrix x, ll n) {
        Matrix res;
        res.setE();
        while(n) {
            if(n & 1)
                res = res * x;
            x = x * x;
            n >>= 1;
        }
        return res;
    }
    
    char ins[8][9];
    char ins2[10][7];
    
    int n, m;
    
    void _setins(int i, int j, int ti, char op) {
        if(op >= '0' && op <= '9') {
            tma[ti].ma[i * m + j][i * m + j] = 1;
            tma[ti].ma[i * m + j][n * m] = op - '0';
        } else if(op == 'D') {
            tma[ti].ma[i * m + j][i * m + j] = 0;
        } else if(op == 'N') {
            tma[ti].ma[i * m + j][i * m + j] = 0;
            if(i > 0) {
                tma[ti].ma[(i - 1)*m + j][i * m + j] = 1;
            }
        } else if(op == 'W') {
            tma[ti].ma[i * m + j][i * m + j] = 0;
            if(j > 0) {
                tma[ti].ma[i * m + j - 1][i * m + j] = 1;
            }
        } else if(op == 'S') {
            tma[ti].ma[i * m + j][i * m + j] = 0;
            if(i + 1 < n) {
                tma[ti].ma[(i + 1)*m + j][i * m + j] = 1;
            }
        } else {
            tma[ti].ma[i * m + j][i * m + j] = 0;
            if(j + 1 < m) {
                tma[ti].ma[i * m + j + 1][i * m + j] = 1;
            }
        }
    }
    
    void setins(int i, int j) {
        int insid = (ins[i][j] - '0');
        char *op = ins2[insid];
        int len = strlen(op);
        int cur = 0;
        for(int ti = 0; ti < 60; ++ti) {
            _setins(i, j, ti, op[cur]);
            ++cur;
            if(cur == len)
                cur = 0;
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        ll T;
        int act;
        while(~scanf("%d%d%lld%d", &n, &m, &T, &act)) {
            for(int i = 0; i < n; ++i)
                scanf("%s", ins[i]);
            for(int a = 0; a < act; ++a) {
                scanf("%s", ins2[a]);
            }
            for(int i = 0; i < 60; ++i) {
                tma[i].init();
                tma[i].ma[n * m][n * m] = 1;
            }
            for(int i = 0; i < n; ++i) {
                for(int j = 0; j < m; ++j)
                    setins(i, j);
            }
    
            /*for(int i = 0; i < 1; ++i) {
                tma[i].show(n * m + 1);
            }*/
    
            Tma.setE();
            for(int i = 0; i < 60; ++i)
                Tma = tma[i] * Tma;
            ll T1 = T / 60;
            Tma = qpow(Tma, T1);
            ll T2 = T % 60;
            for(int i = 0; i < T2; ++i) {
                Tma = tma[i] * Tma;
                //Tma.show(n * m + 1);
            }
    
            F.init();
            F.ma[n * m][0] = 1;
            //F.show(n * m + 1);
    
            F = Tma * F;
    
            //F.show(n * m + 1);
            ll maxans = 0;
            for(int i = 0; i < n * m; ++i) {
                maxans = max(maxans, F.ma[i][0]);
            }
            printf("%lld
    ", maxans);
        }
    }
    
  • 相关阅读:
    虚拟化碎片知识
    CentOS升级内核及KVM安装(已试验,可行)
    Libvirt 虚拟化库剖析
    [ACM]Max Sum
    [ACM]n a^o7 !
    [java]ActionEvent事件:获取输入字符串的长度
    [ACM]The Best Seat in ACM Contest
    [java]ItemEvent事件:简单计算器
    通过注册表的句柄得到当前句柄在注册表中的路径
    [测试模式]Setup方法的滥用
  • 原文地址:https://www.cnblogs.com/Inko/p/11544184.html
Copyright © 2011-2022 走看看