2012-2013 ACM-ICPC, Asia Tokyo Regional Contest

https://codeforces.com/gym/101412

C - One-Dimensional Cellular Automaton

签到题,就是直接矩阵快速幂,一开始用longlong然后到处取模导致T了一发,卡常之后才过。

测出来了,取模大概是11倍常数,鉴于大概元素的范围是2^16次方,所以认为取模是近似一个log是可以的,毕竟本质是移位和乘法和加法神奇的编译器除法优化。就算乘法也是并行的,那也是几倍常数,而且假如不开O2就直接是除法和减法,这就完蛋了。

所以说矩阵的模板要设置上限n,特别是多组数据的那种,不要每次都MAXN。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
int mod;
 
struct Matrix {
    static const int MAXN = 50;
    int ma[MAXN][MAXN], n;
    Matrix(int _n) {
        n = _n;
        init();
    }
    void init() {
        memset(ma, 0, sizeof(ma));
    }
    void setE() {
        init();
        for(int i = 0; i < n; ++i)
            ma[i][i] = 1;
    }
    Matrix operator*(const Matrix &x)const {
        Matrix res(x.n);
        for(int k = 0; k < n; ++k) {
            for(int i = 0; i < n; ++i) {
                register int r = ma[i][k];
                for(int j = 0; j < n; ++j)
                    res.ma[i][j] += r * x.ma[k][j];
            }
        }
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j)
                res.ma[i][j] %= mod;
        }
        return res;
    }
};
 
Matrix qpow(Matrix x, ll n) {
    Matrix res(x.n);
    res.setE();
    while(n) {
        if(n & 1)
            res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}
 
int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    int n, m, a, b, c, t;
    while(~scanf("%d%d%d%d%d%d", &n, &m, &a, &b, &c, &t)) {
        if(n == 0 && m == 0 && a == 0 && b == 0 && c == 0 && t == 0)
            break;
        mod = m;
 
        Matrix F(n), A(n);
        for(int i = 0; i < n; ++i)
            scanf("%d", &F.ma[i][0]);
 
        for(int i = 0; i < n; ++i) {
            if(i - 1 >= 0)
                A.ma[i][i - 1] = a;
            A.ma[i][i] = b;
            if(i + 1 < n)
                A.ma[i][i + 1] = c;
        }
        A = qpow(A, t);
        F = A * F;
        for(int i = 0; i < n; ++i)
            printf("%d%c", F.ma[i][0], " \n"[i == n - 1]);
    }
}

D - Find the Outlier

上一篇:线段树合并学习笔记(P4556)


下一篇:输入输出联系(求学生平均成绩)