T1
神题
看看题解:
std12K:
#include <bits/stdc++.h>
inline int read() {
int ret, cc, sign = 1;
while (!isdigit(cc = getchar()))
sign = cc == '-' ? -1 : sign;
ret = cc - 48;
while (isdigit(cc = getchar()))
ret = cc - 48 + ret * 10;
return ret * sign;
}
const int MOD = 998244353;
const int GEN = 3;
const int Inf = 0x3f3f3f3f;
const int MAXN = 3010;
inline int add(int a, int b) { return (a += b) >= MOD ? a - MOD : a; }
inline int sub(int a, int b) { return (a -= b) < 0 ? a + MOD : a; }
inline int mul(int a, int b) { return 1ll * a * b % MOD; }
inline void inc(int &a, int b) { (a += b) >= MOD ? a -= MOD : a; }
inline void dec(int &a, int b) { (a -= b) < 0 ? a += MOD : a; }
inline int qpow(int a, int p) {
int ret = 1;
p += (p < 0) * (MOD - 1);
for (; p; p >>= 1, a = mul(a, a))
if (p & 1) ret = mul(ret, a);
return ret;
}
struct Graph {
int to[MAXN];
int head[MAXN];
int next[MAXN];
int e_cnt;
inline void insert(int u, int v) {
to[++e_cnt] = v, next[e_cnt] = head[u], head[u] = e_cnt;
to[++e_cnt] = u, next[e_cnt] = head[v], head[v] = e_cnt;
}
Graph() : e_cnt(1) { }
} G;
typedef std::vector<int> Poly;
typedef std::vector<Poly> Func;
inline Poly operator * (const Poly&, const Poly&);
inline Poly operator + (const Poly&, const int&);
inline Poly operator + (const int&, const Poly&);
inline Poly operator + (const Poly&, const Poly&);
inline Poly operator - (const Poly&, const int&);
inline Poly operator - (const int&, const Poly&);
inline Poly operator - (const Poly&, const Poly&);
inline Poly operator * (const Poly&, const Poly&);
inline Poly operator + (const Poly&, const Poly&);
inline Poly operator - (const Poly&, const Poly&);
inline Poly Inverse(const Poly&);
inline Poly Ln(const Poly&);
inline Poly Exp(const Poly&);
inline Poly Pow(const Poly&, int);
inline Poly Sqrt(const Poly&);
inline void Print(const Poly&);
inline Poly Derivate(const Poly&);
inline Poly Integrate(const Poly&);
inline int Integrate(const Poly&, int, int);
inline int Eval(const Poly&, int);
inline int Eval(const Func&, int);
inline void Print(const Poly&);
const Poly X({0, 1});
int C[MAXN][MAXN];
inline Func operator * (const Func& lhs, const Func& rhs) {
Func ret(std::max(lhs.size(), rhs.size()));
for (size_t i = 0; i < ret.size(); ++i) {
if (i < lhs.size() && i < rhs.size())
ret[i] = lhs[i] * rhs[i];
else if (i < lhs.size())
ret[i] = lhs[i];
else
ret[i] = rhs[i];
}
return ret;
}
inline Func operator * (const Func& lhs, const Poly& rhs) {
Func ret(lhs.size());
for (size_t i = 0; i < ret.size(); ++i)
ret[i] = lhs[i] * rhs;
return ret;
}
inline Func operator + (const Func& lhs, const Func& rhs) {
Func ret(std::max(lhs.size(), rhs.size()));
for (size_t i = 0; i < ret.size(); ++i) {
ret[i] = (i < lhs.size() ? lhs[i] : Poly()) +
(i < rhs.size() ? rhs[i] : Poly());
}
return ret;
}
inline Func operator - (const Func& lhs, const Func& rhs) {
Func ret(std::max(lhs.size(), rhs.size()));
for (size_t i = 0; i < ret.size(); ++i) {
ret[i] = (i < lhs.size() ? lhs[i] : Poly()) -
(i < rhs.size() ? rhs[i] : Poly());
}
return ret;
}
inline Poly Shift(const Poly &A, int x) {
Poly a(A.size()), b(A.size());
b[0] = 1, x = (x + MOD) % MOD;
for (size_t i = 1; i < b.size(); ++i)
b[i] = mul(b[i - 1], x);
for (size_t i = 0; i < a.size(); ++i)
for (size_t j = 0; j <= i; ++j) {
inc(a[j], mul(A[i], mul(C[i][j], b[i - j])));
}
return a;
}
inline Func Shift(const Func& A, int x) {
Func a;
for (int i = 0; i + x < (int)(A.size()); ++i) {
a.push_back(i + x >= 0 ? Shift(A[i + x], x) : Poly{0});
}
return a;
}
inline Func Integrate(const Func& lhs) {
Func ret(lhs.size());
for (size_t i = 0; i < ret.size(); ++i) {
ret[i] = Integrate(lhs[i]);
inc(ret[i][0], sub(i ? Eval(ret[i - 1], i) : 0, Eval(ret[i], i)));
}
return ret;
}
inline Func Derivate(const Func& lhs) {
Func ret(lhs.size());
for (size_t i = 0; i < lhs.size(); ++i)
ret[i] = Derivate(lhs[i]);
return ret;
}
inline Func Add(const Func& a) {
if (a.empty()) return Func{X};
Func ret(a.size() + 1);
Func b = Integrate(a), c = Shift(b, -1);
//Print(c);
for (size_t i = 0; i < a.size(); ++i)
ret[i] = b[i] - c[i];
ret.back() = Poly{MOD - (int)a.size(), 1};
ret.back() = ret.back() - c[a.size()];
inc(ret.back()[0], Eval(b, a.size()));
return ret;
}
inline Func Max(const Func& a, const Func& b) {
return a * b;
}
inline int Eval(const Func& a, int x) {
return Eval(a[std::max(std::min((int)a.size() - 1, x), 0)], x);
}
inline void Print(const Func& a) {
for (auto p : a) {
for (auto x : p)
printf("%d ", x);
puts("");
}
puts("");
}
Func F[MAXN];
Func Dp(int u, int fr) {
if (!F[fr].empty())
return F[fr];
for (int e = G.head[u]; e; e = G.next[e])
if (e != (fr ^ 1)) {
F[fr] = Max(F[fr], Add(Dp(G.to[e], e)));
}
return F[fr];
}
inline int Calc(const Func& a) {
int ret = 0;
//Print(a);
Func f1 = Integrate(a * X);
inc(ret, sub(Eval(f1, 1), Eval(f1, 0)));
f1 = Integrate(Integrate(Derivate(a) * X));
inc(ret, sub(Eval(f1, 1), Eval(f1, 0)));
//std::cerr << ret << std::endl;
return ret;
}
inline int Calc(Func a, Func b) {
int ret = 0;
int lena = a.size(), lenb = b.size();
int maxlen = std::max(lena, lenb);
while (a.size() < maxlen + 5u) a.emplace_back(1, 1);
while (b.size() < maxlen + 5u) b.emplace_back(1, 1);
Func c, d, e, f, g;
c = b * X;
d = Integrate(c);
e = Shift(d, 1) - d;
d = Integrate(b);
f = Shift(d, 1) - d;
f = f * X;
f = e - f - b * Poly{(MOD + 1) >> 1};
g = Integrate(Derivate(a) * f);
inc(ret, sub(Eval(g, lena), Eval(g, 0)));
c = Shift(b, 1) - b;
c = c * Poly{1, 1};
d = Integrate(Derivate(b) * X);
e = Shift(d, 1) - d;
f = c - e;
g = Integrate(Derivate(a) * f * X);
inc(ret, sub(Eval(g, lena), Eval(g, 0)));
c = a - Shift(a, -1);
c = c * Poly{1, MOD - 1};
d = Integrate(Derivate(a) * X);
e = d - Shift(d, -1);
f = c + e;
g = Integrate(Derivate(b) * f * X);
inc(ret, sub(Eval(g, lenb), Eval(g, 0)));
return ret;
}
std::pair<int, int> E[MAXN];
inline int Calc(int x) {
Func fx = Dp(E[x].first, x << 1 | 1);
Func fy = Dp(E[x].second, x << 1);
if (fx.empty() && fy.empty()) {
return qpow(2, MOD - 2);
} else if (fx.empty()) {
return Calc(fy);
} else if (fy.empty()) {
return Calc(fx);
} else {
return add(Calc(fx, fy), Calc(fy, fx));
}
}
int n;
int main() {
freopen("expectation.in","r",stdin);
freopen("expectation.out","w",stdout);
n = read();
for (int i = 1; i < n; ++i) {
E[i].first = read(), E[i].second = read();
G.insert(E[i].first, E[i].second);
}
for (int i = (C[0][0] = 1); i < MAXN; ++i)
for (int j = (C[i][0] = 1); j <= i; ++j)
C[i][j] = add(C[i - 1][j], C[i - 1][j - 1]);
int ans = 0;
for (int i = 1; i < n; ++i)
inc(ans, Calc(i));
printf("%d\n", ans);
}
inline void Print(const Poly& rhs) {
for (auto x : rhs)
printf("%d ", x);
puts("");
}
int rev[MAXN];
int W[MAXN];
inline int getrev(int n) {
int len = 1, cnt = 0;
while (len < n) len <<= 1, ++cnt;
for (int i = 0; i < len; ++i)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (cnt - 1));
return len;
}
inline void NTT(Poly& a, int n, int opt) {
a.resize(n);
for (int i = 0; i < n; ++i)
if (i < rev[i])
std::swap(a[i], a[rev[i]]);
W[0] = 1;
for (int i = 1; i < n; i <<= 1) {
int wn = qpow(GEN, opt * (MOD - 1) / (i << 1));
for (int k = i - 2; k >= 0; k -= 2)
W[k + 1] = mul(W[k] = W[k >> 1], wn);
for (int j = 0, p = i << 1; j < n; j += p) {
for (int k = 0; k < i; ++k) {
int x = a[j + k], y = mul(W[k], a[j + k + i]);
a[j + k] = add(x, y), a[j + k + i] = sub(x, y);
}
}
}
if (opt == -1)
for (int i = 0, r = qpow(n, MOD - 2); i < n; ++i)
a[i] = mul(a[i], r);
}
inline Poly operator * (const Poly& lhs, const Poly& rhs) {
if (lhs.size() * rhs.size() <= 2000) {
Poly ret(lhs.size() + rhs.size() - 1);
for (size_t i = 0; i < lhs.size(); ++i)
for (size_t j = 0; j < rhs.size(); ++j)
inc(ret[i + j], mul(lhs[i], rhs[j]));
return ret;
}
Poly A(lhs), B(rhs);
int len = A.size() + B.size() - 1;
int bln = getrev(len);
NTT(A, bln, 1), NTT(B, bln, 1);
for (int i = 0; i < bln; ++i)
A[i] = mul(A[i], B[i]);
NTT(A, bln, -1), A.resize(len);
return A;
}
inline Poly operator + (const Poly& lhs, const Poly& rhs) {
Poly ret(std::max(lhs.size(), rhs.size()));
for (size_t i = 0; i < ret.size(); ++i)
ret[i] = add(i < lhs.size() ? lhs[i] : 0, i < rhs.size() ? rhs[i] : 0);
return ret;
}
inline Poly operator + (const Poly& lhs, const int& c) {
Poly ret(lhs);
inc(ret[0], c);
return ret;
}
inline Poly operator + (const int& c, const Poly& rhs) {
Poly ret(rhs);
inc(ret[0], c);
return ret;
}
inline Poly operator - (const Poly& lhs, const int& c) {
Poly ret(lhs);
dec(ret[0], c);
return ret;
}
inline Poly operator - (const int& c, const Poly& rhs) {
Poly ret(rhs);
dec(ret[0], c);
for (int &x : ret) x = MOD - x;
return ret;
}
inline Poly operator - (const Poly& lhs, const Poly& rhs) {
Poly ret(std::max(lhs.size(), rhs.size()));
for (size_t i = 0; i < ret.size(); ++i)
ret[i] = sub(i < lhs.size() ? lhs[i] : 0, i < rhs.size() ? rhs[i] : 0);
return ret;
}
std::vector<int> getinv() {
std::vector<int> inv(MAXN);
inv[1] = 1;
for (int i = 2; i < MAXN; ++i)
inv[i] = mul(MOD - MOD / i, inv[MOD % i]);
return inv;
}
std::vector<int> Inv = getinv();
inline Poly Derivate(const Poly& A) {
Poly C(A.size() - 1);
for (size_t i = 0; i < C.size(); ++i)
C[i] = mul(i + 1, A[i + 1]);
return C;
}
inline Poly Integrate(const Poly& A) {
Poly C(A.size() + 1);
for (size_t i = 1; i < C.size(); ++i)
C[i] = mul(Inv[i], A[i - 1]);
return C;
}
inline Poly Eval(const Poly& A, const Poly& x) {
Poly ret(1, A.back());
for (int i = (int)(A.size()) - 2; i >= 0; --i)
ret = (ret * x) + A[i];
return ret;
}
inline int Eval(const Poly& A, int x) {
int ret = A.back();
for (int i = (int)(A.size()) - 2; i >= 0; --i)
ret = add(mul(ret, x), A[i]);
return ret;
}
inline int Integrate(const Poly& A, int l, int r) {
Poly C(Integrate(A));
return sub(Eval(C, r), Eval(C, l));
}
inline Poly Inverse(const Poly& A) {
Poly B(1, qpow(A[0], MOD - 2));
int n = A.size() << 1;
for (int i = 2; i < n; i <<= 1) {
Poly C(A); C.resize(i);
int len = getrev(i << 1);
NTT(B, len, 1), NTT(C, len, 1);
for (int j = 0; j < len; ++j)
B[j] = mul(B[j], sub(2, mul(B[j], C[j])));
NTT(B, len, -1), B.resize(i);
}
B.resize(A.size());
return B;
}
inline Poly Ln(const Poly& A) {
Poly C = Integrate(Derivate(A) * Inverse(A));
C.resize(A.size());
return C;
}
inline Poly Exp(const Poly& A) {
Poly B(1, 1);
int n = A.size() << 1;
for (int i = 2; i < n; i <<= 1) {
Poly C(A);
C.resize(i), B.resize(i);
B = B * (Poly(1, 1) - Ln(B) + C);
}
B.resize(A.size());
return B;
}
inline Poly Pow(const Poly& A, int k) {
Poly C(Ln(A));
for (size_t i = 0; i < C.size(); ++i)
C[i] = mul(C[i], k);
return Exp(C);
}
inline Poly Sqrt(const Poly& A) {
Poly C(A);
int c = A[0], ic = qpow(c, MOD - 2);
for (size_t i = 0; i < C.size(); ++i)
C[i] = mul(C[i], ic);
c = sqrt(c), C = Pow(C, Inv[2]);
for (size_t i = 0; i < C.size(); ++i)
C[i] = mul(C[i], c);
return C;
}
T2
子序列问题想到DP,发现可以用矩阵优化DP。那么预处理出来前缀矩阵和前缀逆矩阵就行了。问题是时间复杂度承受不起。解决方法是观察矩阵特点:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
const int MAXM = 60;
const int C = 52;
const int mod = 998244353;
inline int get(char ch) { return ch >= 'a' ? ch-'a'+26 : ch-'A'; }
char s[MAXN];
int n, q;
int mat[MAXM][MAXM], s1[MAXN][MAXM], s2[MAXN][MAXM], hs[MAXM], tag[MAXM];
int main () {
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
scanf("%s", s+1); n = strlen(s+1);
for(int i = 0; i <= C; ++i) hs[i] = mat[i][i] = 1;
for(int i = 1; i <= n; ++i) {
int x = get(s[i]);
for(int j = 0; j <= C; ++j) {
int tmp = mat[j][x];
mat[j][x] = hs[j];
s1[i][j] = hs[j] = (hs[j] + (mat[j][x] + mod - tmp) % mod) % mod;
}
}
memset(mat, 0, sizeof mat);
for(int i = 0; i <= C; ++i) mat[i][i] = 1;
for(int i = 1; i <= n; ++i) {
int x = get(s[i]);
for(int j = 0; j <= C; ++j) {
mat[x][j] = (mat[x][j] + tag[j]) % mod;
tag[j] = (tag[j] + mod - mat[x][j]) % mod;
mat[x][j] = (mat[x][j] + mod - tag[j]) % mod;
}
for(int j = 0; j <= C; ++j)
s2[i][j] = (mat[C][j] + tag[j]) % mod;
}
int ta, tb, a, b, x, y, z = 0, p, q, r;
scanf("%d%d%d%d%d%d", &q, &a, &b, &p, &q, &r);
for(int i = 1; i <= q; ++i) {
ta = (1ll * p * a + 1ll * q * b + z + r) % mod;
tb = (1ll * p * b + 1ll * q * a + z + r) % mod;
x = min(ta % n, tb % n) + 1;
y = max(ta % n, tb % n) + 1;
a = ta, b = tb;
if(x == 1) z = s1[y][C];
else {
z = 0;
for(int j = 0; j <= C; ++j)
z = (z + 1ll * s2[x-1][j] * s1[y][j]) % mod;
}
}
printf("%d\n", z);
}
T3
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 105;
const int mod = 998244353;
int n, f[MAXN*MAXN][MAXN][MAXN];
inline void add(int &x, int y) { x += y; x >= mod ? x -= mod : 0; }
int main () {
freopen("counting.in", "r", stdin);
freopen("counting.out", "w", stdout);
scanf("%d", &n);
f[0][1][1] = 1;
for(int i = 0; i < n*(n-1); ++i)
for(int j = 1, lj = min(n, i+(i==0)); j <= lj; ++j)
for(int k = j, lk = min(n, i+1); k <= lk; ++k) if(f[i][j][k]) {
if(k < n) add(f[i+1][j][k+1], f[i][j][k]);
else if(i < (k*(k-1) + j*(j-1))/2) add(f[i+1][j][k], f[i][j][k]);
for(int l = j+1; l <= k; ++l) add(f[i+1][l][k], f[i][j][k]);
}
for(int i = 1; i <= n*(n-1); ++i) {
int ans = 0;
for(int j = 1, lj = min(n, i); j <= lj; ++j)
for(int k = j, lk = min(n, i+1); k <= lk; ++k)
add(ans, f[i][j][k]);
printf("%d%c", ans, " \n"[i == n*(n-1)]);
}
}