https://codeforces.com/gym/101412
C - 一次元セルオートマトン
サイン質問は、剰余が状況につながっどこでも、それはその後、LONGLONGで始まる、直接行列高速電力であるだけで、多くの場合、カードの後にした後、Tを得ました。
量り、弾性率は2 ^ 16電源、弾性率が約ログは、すべての後に、実質的に可能なシフトと乗算および加算であると考えられているされている要素のおおよその範囲を考慮すると、約11倍で一定である魔法コンパイラ分割最適化。乗算は並列であっても、それが何回か一定であり、彼らは直接開けない場合は、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 - 外れ値を探します