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