QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#542905 | #1846. Nimber Sequence | ohwphil | AC ✓ | 225ms | 13064kb | C++17 | 7.8kb | 2024-09-01 07:48:45 | 2024-09-01 07:48:45 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
// nimber by hos_lyric
// https://github.com/hos-lyric/libra/blob/master/algebra/nimber.h
////////////////////////////////////////////////////////////////////////////////
namespace nim {
using u16 = unsigned short;
using u32 = unsigned;
using u64 = unsigned long long;
// G16: primitive root in F_(2^16)
// G16\^3 = 2^15
constexpr u16 G16 = 10279U;
u16 expBuffer[4 * (1 << 16) + 4];
u16 *exp = expBuffer + (2 * (1 << 16) + 4), *exp3 = exp + 3, *exp6 = exp + 6;
int log[1 << 16];
u64 tabSq[4][1 << 16], tabSqrt[4][1 << 16], tabSolveQuad1[4][1 << 16];
// L: power of 2
// (a0 + 2^l a1) \* (b0 + 2^l b1)
// = (a0\*b0 \+ 2^(l-1)\*a1\*b1) + 2^l (a0\*b1 \+ a1\*b0 \+ a1\*b1)
template <int L> inline u64 mulSlow(u64 a, u64 b) {
static constexpr int l = L >> 1;
const u64 a0 = a & ((1ULL << l) - 1), a1 = a >> l;
const u64 b0 = b & ((1ULL << l) - 1), b1 = b >> l;
const u64 a0b0 = mulSlow<l>(a0, b0);
return (a0b0 ^ mulSlow<l>(1ULL << (l - 1), mulSlow<l>(a1, b1)))
| (a0b0 ^ mulSlow<l>(a0 ^ a1, b0 ^ b1)) << l;
}
template <> inline u64 mulSlow<1>(u64 a, u64 b) {
return a & b;
}
// 2^31 \* a
inline u32 mul31(u32 a) {
const u16 a0 = a, a1 = a >> 16;
const u16 a01 = a0 ^ a1;
return exp6[log[a1]] | (u32)exp3[log[a01]] << 16;
}
inline u16 mul(u16 a, u16 b) {
return exp[log[a] + log[b]];
}
inline u32 mul(u32 a, u32 b) {
const u16 a0 = a, a1 = a >> 16;
const u16 b0 = b, b1 = b >> 16;
const u16 a01 = a0 ^ a1;
const u16 b01 = b0 ^ b1;
const u16 a0b0 = mul(a0, b0);
return (a0b0 ^ exp3[log[a1] + log[b1]]) | (u32)(a0b0 ^ mul(a01, b01)) << 16;
}
inline u64 mul(u64 a, u64 b) {
const u32 a0 = a, a1 = a >> 32;
const u32 b0 = b, b1 = b >> 32;
const u32 a01 = a0 ^ a1;
const u32 b01 = b0 ^ b1;
const u32 a0b0 = mul(a0, b0);
return (a0b0 ^ mul31(mul(a1, b1))) | (u64)(a0b0 ^ mul(a01, b01)) << 32;
}
inline u16 sq(u16 a) {
return tabSq[0][a];
}
inline u32 sq(u32 a) {
const u16 a0 = a, a1 = a >> 16;
return tabSq[0][a0] ^ tabSq[1][a1];
}
inline u64 sq(u64 a) {
const u16 a0 = a, a1 = a >> 16, a2 = a >> 32, a3 = a >> 48;
return tabSq[0][a0] ^ tabSq[1][a1] ^ tabSq[2][a2] ^ tabSq[3][a3];
}
inline u16 sqrt(u16 a) {
return tabSqrt[0][a];
}
inline u32 sqrt(u32 a) {
const u16 a0 = a, a1 = a >> 16;
return tabSqrt[0][a0] ^ tabSqrt[1][a1];
}
inline u64 sqrt(u64 a) {
const u16 a0 = a, a1 = a >> 16, a2 = a >> 32, a3 = a >> 48;
return tabSqrt[0][a0] ^ tabSqrt[1][a1] ^ tabSqrt[2][a2] ^ tabSqrt[3][a3];
}
// (a0 + 2^l a1) \* (b0 + 2^l b1) = 1
// <=> [ a0 2^(l-1)\*a1 ] \* [ b0 ] = [ 1 ]
// [ a1 a0\+a1 ] [ b1 ] [ 0 ]
inline u16 inv(u16 a) {
assert(a);
return exp[((1 << 16) - 1) - log[a]];
}
inline u32 inv(u32 a) {
assert(a);
const u16 a0 = a, a1 = a >> 16;
const u16 a01 = a0 ^ a1;
const u16 d = inv((u16)(mul(a0, a01) ^ exp3[log[a1] + log[a1]]));
return mul(d, a01) | (u32)mul(d, a1) << 16;
}
inline u64 inv(u64 a) {
assert(a);
const u32 a0 = a, a1 = a >> 32;
const u32 a01 = a0 ^ a1;
const u32 d = inv(mul(a0, a01) ^ mul31(sq(a1)));
return mul(d, a01) | (u64)mul(d, a1) << 32;
}
// f(x) := x\^2 \+ x
// bsr(x\^2) = bsr(x)
// f: {even in [0, 2^L)} -> [0, 2^(L-1)): linear isom.
// f(x0 + 2^l x1) = (f(x0) \+ 2^(l-1)\*x1\^2) + 2^l f(x1)
template <int L> inline u64 solveQuad1Slow(u64 a) {
static constexpr int l = L >> 1;
assert(!(a >> (L - 1)));
const u64 a0 = a & ((1ULL << l) - 1), a1 = a >> l;
const u64 x1 = solveQuad1Slow<l>(a1);
const u64 b0 = a0 ^ mul(1ULL << (l - 1), sq(x1));
const u64 s = b0 >> (l - 1);
return solveQuad1Slow<l>(b0 ^ s << (l - 1)) | (x1 ^ s) << l;
}
template <> inline u64 solveQuad1Slow<1>(u64 a) {
assert(!a);
return 0;
}
// x\^2 \+ x \+ a = 0
// solutions: x, x \+ 1
inline u64 solveQuad1(u64 a) {
assert(!(a >> 63));
const u16 a0 = a, a1 = a >> 16, a2 = a >> 32, a3 = a >> 48;
return tabSolveQuad1[0][a0] ^ tabSolveQuad1[1][a1] ^ tabSolveQuad1[2][a2] ^ tabSolveQuad1[3][a3];
}
// x\^2 \+ a\*x \+ b = 0
// solutions: x, x \+ a
inline bool isSolvableQuad(u64 a, u64 b) {
return !(mul(inv(sq(a)), b) >> 63);
}
inline u64 solveQuad(u64 a, u64 b) {
return a ? mul(a, solveQuad1(mul(inv(sq(a)), b))) : sqrt(b);
}
struct Preparator {
Preparator() {
exp[0] = 1;
for (int i = 1; i < (1 << 16) - 1; ++i) exp[i] = mulSlow<16>(exp[i - 1], G16);
for (int i = (1 << 16) - 1; i < 2 * (1 << 16); ++i) exp[i] = exp[i - ((1 << 16) - 1)];
for (int i = 0; i < (1 << 16) - 1; ++i) log[exp[i]] = i;
log[0] = -(1 << 16) - 2;
for (int e = 0; e < 64; ++e) {
const u64 x = mul(1ULL << e, 1ULL << e);
for (int i = 0; i < 1 << (e & 15); ++i) tabSq[e >> 4][i | 1 << (e & 15)] = tabSq[e >> 4][i] ^ x;
}
for (int e = 0; e < 64; ++e) {
u64 x = 1ULL << e;
for (int j = 0; j < 63; ++j) x = sq(x);
for (int i = 0; i < 1 << (e & 15); ++i) tabSqrt[e >> 4][i | 1 << (e & 15)] = tabSqrt[e >> 4][i] ^ x;
}
for (int e = 0; e < 63; ++e) {
const u64 x = solveQuad1Slow<64>(1ULL << e);
for (int i = 0; i < 1 << (e & 15); ++i) tabSolveQuad1[e >> 4][i | 1 << (e & 15)] = tabSolveQuad1[e >> 4][i] ^ x;
}
}
} preparator;
} // namespace nim
////////////////////////////////////////////////////////////////////////////////
long long k, m;
vector<nim::u32> f, g;
vector<nim::u32> terms;
nim::u32 temp;
vector<nim::u32> mul_by_small_poly(vector<nim::u32>& big_poly, vector<nim::u32>& small_poly) {
vector<nim::u32> result(big_poly.size() + small_poly.size() - 1, 0);
for (int i = 0; i < big_poly.size(); i++) {
for (int j = 0; j < small_poly.size(); j++) {
result[i + j] ^= nim::mul(big_poly[i], small_poly[j]);
}
}
return result;
}
vector<nim::u32> mul_by_f_and_g(vector<nim::u32>& big_poly, vector<nim::u32>& ff, vector<nim::u32>& gg) {
vector<nim::u32> big_poly_times_f = mul_by_small_poly(big_poly, ff);
big_poly_times_f.resize(big_poly.size() + k - 1);
vector<nim::u32> big_poly_times_g = mul_by_small_poly(big_poly, gg);
for (int i = 0; i < big_poly_times_g.size(); i++) {
big_poly_times_f[i + k - 5] ^= big_poly_times_g[i];
}
return big_poly_times_f;
}
nim::u32 bostan_mori(vector<nim::u32>& terms_times_poly, long long term_num) {
vector<nim::u32> p = terms_times_poly;
vector<nim::u32> ff = f;
vector<nim::u32> gg = g;
while (term_num) {
vector<nim::u32> u = mul_by_f_and_g(p, ff, gg);
vector<nim::u32> temp_ff = mul_by_small_poly(ff, ff);
vector<nim::u32> temp_gg = mul_by_small_poly(gg, gg);
ff.clear();
gg.clear();
for (int i = 0; i < temp_ff.size(); i++) {
if (i % 2 == 0) {
ff.push_back(temp_ff[i]);
}
}
for (int i = 0; i < temp_gg.size(); i++) {
if (i % 2 == 0) {
gg.push_back(temp_gg[i]);
}
}
vector<nim::u32> temp_p;
for (int i = 0; i < u.size(); i++) {
if (i % 2 == term_num % 2) {
temp_p.push_back(u[i]);
}
}
p = temp_p;
term_num >>= 1;
}
return p[0];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> k >> m;
m--;
f.push_back(1);
for (int i = 0; i < k - 1; i++) {
cin >> temp;
terms.push_back(temp);
}
for (int i = 0; i < 5; i++) {
cin >> temp;
f.push_back(temp);
}
g.resize(5);
for (int i = 4; i >= 0; i--) {
cin >> temp;
g[i] = temp;
}
vector<nim::u32> terms_times_poly = mul_by_f_and_g(terms, f, g);
terms_times_poly.resize(k - 1);
cout << bostan_mori(terms_times_poly, m) << '\n';
return 0;
}
詳細信息
Test #1:
score: 100
Accepted
time: 6ms
memory: 9980kb
input:
6 1000000000000000000 1 2 3 4 5 1 0 0 0 0 0 0 0 0 0
output:
5
result:
ok 1 number(s): "5"
Test #2:
score: 0
Accepted
time: 3ms
memory: 10240kb
input:
6 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
output:
9
result:
ok 1 number(s): "9"
Test #3:
score: 0
Accepted
time: 5ms
memory: 10200kb
input:
11 123 849 674 223 677 243 657 979 583 643 845 979 282 313 567 433 122 443 132 554 132
output:
32098
result:
ok 1 number(s): "32098"
Test #4:
score: 0
Accepted
time: 208ms
memory: 13064kb
input:
94687 710570983697626969 4186557624 1758948383 1525259816 3101110545 68985505 4021660545 2620109458 3527848853 1499791593 260558927 1389587540 437663963 3321035637 3011275742 1039744828 1589760367 560359358 3134457958 904931985 2662313614 1297047424 3811720281 1035292586 197000110 1933020394 3960145...
output:
3006077279
result:
ok 1 number(s): "3006077279"
Test #5:
score: 0
Accepted
time: 185ms
memory: 12320kb
input:
79613 926807680470549574 240717113 1392667289 600326755 3006189729 1036763966 4200370649 832885304 3179580334 252290394 1868105288 25303456 1296253738 1782285727 3393497795 2807990600 636856662 3249311526 931051890 711882668 2026982742 2203064601 294534169 129793188 3651587530 204310179 1796272964 3...
output:
802548440
result:
ok 1 number(s): "802548440"
Test #6:
score: 0
Accepted
time: 225ms
memory: 12916kb
input:
99038 715717879221820711 885061248 3555700514 3820685873 4053621020 3180859383 299397751 3217820490 3205780111 1121090479 2882329235 528034852 3592056293 1665426454 1068065389 856025265 854138116 667671416 3918114401 47824602 1691900065 1778784903 549871974 3814813604 19170756 3334936314 878165712 2...
output:
2619227590
result:
ok 1 number(s): "2619227590"
Test #7:
score: 0
Accepted
time: 163ms
memory: 11940kb
input:
70227 527188874142225860 3382516938 336014844 4232905832 2339685992 608249855 1965447517 861112037 1960852035 4255277552 1485868169 1253940594 3242731487 4136361436 2912276941 606973532 2391974159 4042484700 2690616307 4164589249 211137598 3922655693 1979705166 43275864 1720206634 4258462080 2922225...
output:
2494358698
result:
ok 1 number(s): "2494358698"
Test #8:
score: 0
Accepted
time: 119ms
memory: 11244kb
input:
50107 636804708634823490 4061423552 3234909964 3382098957 3722938836 1308363694 3689294223 392722027 853196829 419234773 1612477793 2615573406 2396449203 3202797971 3169875659 3708337029 1502000395 2100156786 551389396 1298315652 3019347781 483421794 4103525227 3141784506 1707389481 891279359 339165...
output:
3106396659
result:
ok 1 number(s): "3106396659"
Test #9:
score: 0
Accepted
time: 132ms
memory: 11580kb
input:
58938 529243871538325664 3020105019 107458139 1358540066 4226585158 1052474383 476581569 1735237989 3149631046 1458669468 4284254999 1884808793 4157959520 1805665783 4240155370 445247262 4250425954 593381324 1086483397 1751880165 3437540518 1725405588 763057742 2484241157 2758482804 621158445 196519...
output:
3333412246
result:
ok 1 number(s): "3333412246"
Test #10:
score: 0
Accepted
time: 140ms
memory: 12184kb
input:
69233 682310983374776172 1429373477 3627364047 4209854869 1669835895 1920629742 487073768 3498638486 1345224323 922818519 706294866 4119891492 3676759264 3996646886 461542924 2095205022 1565132423 1079680977 2999129158 2674541458 4198342822 2533846170 1646428648 2173849932 1577205648 3630140894 1879...
output:
3405368155
result:
ok 1 number(s): "3405368155"
Test #11:
score: 0
Accepted
time: 0ms
memory: 10272kb
input:
9 5985 95 17 77 97 38 90 30 98 27 99 36 83 90 78 58 24 9 59
output:
61
result:
ok 1 number(s): "61"
Test #12:
score: 0
Accepted
time: 0ms
memory: 9920kb
input:
65 697938 33 11 67 18 20 17 49 86 83 19 54 49 2 80 79 65 47 48 89 89 23 42 0 51 28 26 28 89 53 19 87 0 50 46 8 23 27 81 10 98 95 23 50 38 91 36 75 72 18 41 72 80 70 39 58 77 90 48 17 91 6 6 72 10 94 46 31 80 19 95 39 73 77 24
output:
90
result:
ok 1 number(s): "90"
Test #13:
score: 0
Accepted
time: 6ms
memory: 10220kb
input:
502 947413402 8091 2795 1172 7759 5749 8805 3262 7053 5600 8158 4241 5232 172 9985 1613 2343 9504 2483 9746 2416 6032 9132 3020 6961 3376 8689 886 4377 4441 6139 3926 1589 2060 8082 7737 5111 7656 4688 6761 4864 5187 6782 8955 9474 2351 1786 1193 2236 7250 7250 5758 1228 452 7499 3744 8264 129 6784 ...
output:
57063
result:
ok 1 number(s): "57063"