barrett
点击查看代码
__int128 mu = -1ull / mod;
inline ll reduce(ll x) {
ll r = x - (mu * x >> 64) * mod;
return r >= mod ? r - mod : r;
}
O(n)-O(1) rmq
点击查看代码
namespace RMQ {
const int N = 1e5 + 5;
const int K = log2(N);
const int M = N / K + 2;
int al, a[N], lg[N], tt[N], lmx[N], rmx[N], pos[N], L[M], R[M], mx[M][21], st[N], stk[K];
int query(int l, int r) {
int p = pos[l], q = pos[r];
if (p == q) return a[tt[st[r] >> (l - L[p])] + l];
if (p == q - 1) return max(rmx[l], lmx[r]);
p++, q--; int k = lg[q - p + 1];
return max(max(mx[p][k], mx[q - (1 << k) + 1][k]), max(rmx[l], lmx[r]));
}
void init(int n) {
for (int i = 2; i <= n; i++) lg[i] = lg[i >> 1] + 1;
for (int i = 1; i <= n; i++) tt[i] = lg[i & -i];
for (int i = 1; ; i++) {
L[i] = R[i - 1] + 1, R[i] = min(n, R[i - 1] + lg[n]);
lmx[L[i]] = a[L[i]], rmx[R[i]] = a[R[i]];
for (int j = L[i] + 1; j <= R[i]; j++) lmx[j] = max(lmx[j - 1], a[j]);
for (int j = R[i] - 1; j >= L[i]; j--) rmx[j] = max(rmx[j + 1], a[j]);
for (int j = L[i], top = 0; j <= R[i]; j++) {
st[j] = j - L[i] ? st[j - 1] : 0;
while (top && a[j] > a[L[i] + stk[top]]) st[j] -= 1 << stk[top--];
st[j] += 1 << (stk[++top] = j - L[i]), pos[j] = i;
}
mx[i][0] = lmx[R[i]]; if (R[i] == n) break;
}
for (int j = 1; j <= lg[pos[n]]; j++) {
for (int i = 1; i + (1 << j) - 1 <= pos[n]; i++) {
mx[i][j] = max(mx[i][j - 1], mx[i + (1 << (j - 1))][j - 1]);
}
}
}
}
整式递推
点击查看代码
vector<vector<int>> find_rel(const vector<int> &a, int deg) {
int n = a.size(), B = (n + 2) / (deg + 2), C = B * (deg + 1), R = n - (B - 1), c = 0;
assert(B >= 2 && R >= C - 1);
vector<vector<int>> b(R, vector<int>(C));
for (int i = 0; i < R; i++) {
for (int j = 0; j < B; j++) {
for (int k = 0, x = a[i + j]; k <= deg; k++, x = (ll)x * (i + j) % mod) {
b[i][j * (deg + 1) + k] = x;
}
}
}
for (c = 0; c < C; c++) {
int p = -1;
for (int i = c; i < R; i++) {
if (b[i][c]) {
p = i;
break;
}
}
if (p == -1) break;
swap(b[p], b[c]);
int w = qpow(b[c][c]);
for (int i = c; i < C; i++) {
b[c][i] = (ll)b[c][i] * w % mod;
}
for (int i = c + 1; i < R; i++) if (b[i][c]) {
int t = b[i][c];
for (int j = c; j < C; j++) {
b[i][j] = (b[i][j] + mod - (ll)b[c][j] * t % mod) % mod;
}
}
}
assert(c != C);
for (int i = c - 1; ~i; i--) if (b[i][c]) {
for (int j = i - 1; ~j; j--) {
b[j][c] = (b[j][c] + mod - (ll)b[i][c] * b[j][i] % mod) % mod;
}
}
int od = c / (deg + 1);
vector<vector<int>> ret(od + 1, vector<int>(deg + 1));
ret[0][c % (deg + 1)] = 1;
for (int i = c - 1; ~i; i--) {
ret[od - i / (deg + 1)][i % (deg + 1)] = mod - b[i][c];
}
for (int i = 0; i <= od; i++) {
vector<int> tmp(deg + 1);
for (int k = 0; k <= deg; k++) {
for (int j = k, s = 1; j <= deg; j++) {
tmp[k] = (tmp[k] + (ll)s * ret[i][j]) % mod;
s = (ll)s * (mod - i) % mod * (j + 1) % mod * qpow(j + 1 - k) % mod;
}
}
ret[i] = tmp;
}
return ret;
}