https://gmoj.net/senior/#main/show/100013
考えてみましょう\(M \ル100 \)一部、行列の乗算を考えることは困難分割を。
ここで、\(および\)は乗算を定義し、\(xor \)は加算として定義され、通常の行列乗算が行われます。
これは、定数係数の均一線形再帰に非常に似ていることがわかりました。
定数係数の同次線形再帰は、\(Mod \)多項式\(M \)です。ここでは、このような類似した多項式も定義できます。
が\(および\)逆数ではない、それは他のすべてのことに留意されたい\(M \)最高アイテム、最高係数\(= 2 ^ {32} -1 \) 、任意の数で割った値数えれば問題ありません。
時間の複雑さ:\(O(n ^ 2〜log〜m)\)
コード:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int N = 2e3 + 5;
#define ui unsigned int
int n; ll m;
ui a[N], b[N];
const ui inf = 4294967295ll;
void qmo(ui *a) {
fd(i, 2 * n, n + 1) if(a[i]) {
fo(j, 1, n) a[i - j] ^= b[j] & a[i];
a[i] = 0;
}
}
ui c[N];
void mul(ui *a, ui *b) {
fo(i, 0, 2 * n) c[i] = 0;
fo(i, 0, n) fo(j, 0, n) c[i + j] ^= a[i] & b[j];
qmo(c);
fo(i, 0, n) a[i] = c[i];
}
ui s[N], x[N];
int main() {
freopen("prophecy.in", "r", stdin);
freopen("prophecy.out", "w", stdout);
scanf("%d", &n);
fo(i, 1, n) scanf("%u", &a[i]);
fo(i, 1, n) scanf("%u", &b[i]);
scanf("%lld", &m);
s[0] = inf; x[1] = inf;
for(; m; m /= 2, mul(x, x))
if(m & 1) mul(s, x);
ui ans = 0;
fo(i, 1, n) ans ^= s[i] & a[i];
pp("%u\n", ans);
}