随机立方体
设$f_i$为恰有$i$个极大值的概率,$g_i$为至少有$i$个极大值的概率。
先求方案数,考虑组合意义,第$i$大的数相当于要是$nml-(n-k+i-1)(m-k+i-1)(l-k+i-1)$个数(包括它直接控制和被比它小的的极大值控制的)中最大的,那么设$h_i$为选$i$个极大值的方案数,则
$$h_i=prod_{j=0}^{i-1}(n-j)(m-j)(l-j)$$
故
$$g_i=h_iprod_{j=1}^ifrac{1}{nml-(n-i+j-1)(m-i+j-1)(l-i+j-1)}$$
又
$$g_i=sum_{j=i}^ninom{j}{i}f_j$$
二项式反演即可,注意线性求逆元。
注意代码里的变量名意义和上面并不一样。
1 #include <bits/stdc++.h> 2 3 #define IL __inline__ __attribute__((always_inline)) 4 5 #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i) 6 #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i) 7 #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i) 8 #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i) 9 10 typedef long long LL; 11 12 template <class T> 13 IL bool chkmax(T &a, const T &b) { 14 return a < b ? ((a = b), 1) : 0; 15 } 16 17 template <class T> 18 IL bool chkmin(T &a, const T &b) { 19 return a > b ? ((a = b), 1) : 0; 20 } 21 22 template <class T> 23 IL T mymax(const T &a, const T &b) { 24 return a > b ? a : b; 25 } 26 27 template <class T> 28 IL T mymin(const T &a, const T &b) { 29 return a < b ? a : b; 30 } 31 32 template <class T> 33 IL T myabs(const T &a) { 34 return a > 0 ? a : -a; 35 } 36 37 const int INF = 0X3F3F3F3F; 38 const double EPS = 1E-8, PI = acos(-1.0); 39 40 #define DEBUG(...) fprintf(stderr, __VA_ARGS__) 41 #define OK DEBUG("Passing [%s] in LINE %d... ", __FUNCTION__, __LINE__) 42 43 const int MAXN = 5000000 + 5; 44 45 namespace Math { 46 const int MOD = 998244353; 47 48 IL int add(int a, int b) { 49 a += b; 50 return a >= MOD ? a - MOD : a; 51 } 52 53 template <class ...Args> 54 IL int add(int a, const Args &...args) { 55 a += add(args...); 56 return a >= MOD ? a - MOD : a; 57 } 58 59 IL int sub(int a, int b) { 60 a -= b; 61 return a < 0 ? a + MOD : a; 62 } 63 64 IL int mul(int a, int b) { 65 return (LL)a * b % MOD; 66 } 67 68 template <class ...Args> 69 IL int mul(int a, const Args &...args) { 70 return (LL)a * mul(args...) % MOD; 71 } 72 73 IL int quickPow(int a, int p) { 74 int result = 1; 75 for (; p; p >>= 1, a = mul(a, a)) { 76 if (p & 1) { 77 result = mul(result, a); 78 } 79 } 80 return result; 81 } 82 } 83 84 using namespace Math; 85 86 int f[MAXN], g[MAXN], inv_g[MAXN], fac[MAXN], ifac[MAXN]; 87 88 IL void init(int n) { 89 fac[0] = 1; 90 For(i, 1, n) { 91 fac[i] = mul(fac[i - 1], i); 92 } 93 ifac[n] = quickPow(fac[n], MOD - 2); 94 REP(i, n, 0) { 95 ifac[i] = mul(ifac[i + 1], i + 1); 96 } 97 } 98 99 IL int binom(int n, int m) { 100 return mul(fac[n], ifac[m], ifac[n - m]); 101 } 102 103 int main() { 104 int T; 105 scanf("%d", &T); 106 while (T --) { 107 int n, m, l, k; 108 scanf("%d%d%d%d", &n, &m, &l, &k); 109 int mult = mul(n, m, l), min = mymin(n, mymin(m, l)); 110 init(min); 111 int cur = 1; 112 f[0] = 1; 113 For(i, 1, min) { 114 f[i] = mul(f[i - 1], n - i + 1, m - i + 1, l - i + 1); 115 g[i] = sub(mult, mul(n - i, m - i, l - i)); 116 cur = mul(cur, g[i]); 117 } 118 inv_g[min] = quickPow(cur, MOD - 2); 119 REP(i, min, 0) { 120 inv_g[i] = mul(inv_g[i + 1], g[i + 1]); 121 } 122 int answer = 0; 123 cur = 1; 124 For(i, k, min) { 125 answer = add(answer, mul(cur, f[i], inv_g[i], binom(i, k))); 126 cur = mul(cur, MOD - 1); 127 } 128 printf("%d ", answer); 129 } 130 return 0; 131 }
珍珠
考虑同一个权值至多贡献一个奇数,那么至多有$n-2m$个权值出现奇数次。
一个权值出现偶数次的EGF是$frac{e^x+e^{-x}}{2}$,出现奇数次的EGF是$frac{e^x-e^{-x}}{2}$。
那么答案就是
$$n!sum_{i=0}^{n-2m}(frac{e^x+e^{-x}}{2}+yfrac{e^x-e^{-x}}{2})^D[x^n][y^i]$$
即
$$n!frac{1}{2^D}sum_{i=0}^{n-2m}((1+y)e^x+(1-y)e^{-x})^D[x^n][y^i]$$
对内层二项式定理展开,则有
$$n!frac{1}{2^D}sum_{i=0}^{n-2m}sum_{j=0}^Dinom{D}{j}e^{(2j-D)x}(1+y)^j(1-y)^{D-j}[x^n][y^i]$$
化开$e^{kx}$,即:
$$frac{1}{2^D}sum_{j=0}^Dinom{D}{j}(2j-D)^nsum_{i=0}^{n-2m}(1+y)^j(1-y)^{D-j}[y^i]$$
接下来是一些神仙内容:
令$F(j,D)=sum_{i=0}^{n-2m}(1+y)^j(1-y)^{D-j}[y^i]$,则
$$egin{aligned}F(j,D)&=sum_{i=0}^{n-2m}(1+y)^j(1-y)^{D-j}[y^i]\&=sum_{i=0}^{n-2m}(1+y)^{j-1}(-(1-y)+2)(1-y)^{D-j}[y^i]\&=-sum_{i=0}^{n-2m}(1+y)^{j-1}(1-y)^{D-j+1}[y^i]+2sum_{i=0}^{n-2m}(1+y)^{j-1}(1-y)^{D-j}[y^i]\&=-F(j-1,D)+2F(j-1,D-1)end{aligned}$$
因为$F(0,D)$是好求的:
$$egin{aligned}F(0,D)&=sum_{i=0}^{n-2m}(1-y)^D[y^i]\&=sum_{i=0}^{n-2m}inom{D}{i}(-1)^i\&=sum_{i=0}^{n-2m}inom{D-1}{i}(-1)^i-sum_{i=0}^{n-2m-1}inom{D-1}{i}(-1)^i\&=inom{D-1}{n-2m}(-1)^{n-2m}end{aligned}$$
那么考虑组合意义,相当于你可以从$(0,k)$走到$(j,D)$,每一步要么向右上走,贡献2,要么向正右方走,贡献-1,那么:
$$F(j,D)=sum_{k=0}^{D}inom{j}{D-k}2^{D-k}(-1)^{j-D+k}F(0,k)$$
然后再拆一下:
$$egin{aligned} ext{answer}&=frac{1}{2^D}sum_{j=0}^Dinom{D}{j}(2j-D)^nF(j,D)\&=frac{1}{2^D}sum_{j=0}^Dinom{D}{j}(2j-D)^nsum_{k=0}^{D}inom{j}{D-k}2^{D-k}(-1)^{j-D+k}F(0,k)\&=frac{D!}{2^D}sum_{j=0}^Dsum_{k=0}^{D}frac{1}{(D-j)!(D-k)!(j-D+k)!}(2j-D)^n2^{D-k}(-1)^{j-D+k}F(0,k)\&=frac{D!}{2^D}sum_{j=0}^Dsum_{k=0}^{D}frac{(-1)^{j+k-D}}{(j+k-D)!}cdotfrac{(2j-D)^n}{(D-j)!}cdotfrac{2^{D-k}F(0,k)}{(D-k)!}end{aligned}$$
就可以卷积了。
注意一些特判。
1 #include <bits/stdc++.h> 2 3 #define IL __inline__ __attribute__((always_inline)) 4 5 #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i) 6 #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i) 7 #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i) 8 #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i) 9 10 typedef long long LL; 11 12 template <class T> 13 IL bool chkmax(T &a, const T &b) { 14 return a < b ? ((a = b), 1) : 0; 15 } 16 17 template <class T> 18 IL bool chkmin(T &a, const T &b) { 19 return a > b ? ((a = b), 1) : 0; 20 } 21 22 template <class T> 23 IL T mymax(const T &a, const T &b) { 24 return a > b ? a : b; 25 } 26 27 template <class T> 28 IL T mymin(const T &a, const T &b) { 29 return a < b ? a : b; 30 } 31 32 template <class T> 33 IL T myabs(const T &a) { 34 return a > 0 ? a : -a; 35 } 36 37 const int INF = 0X3F3F3F3F; 38 const double EPS = 1E-8, PI = acos(-1.0); 39 40 #define DEBUG(...) fprintf(stderr, __VA_ARGS__) 41 #define OK DEBUG("Passing [%s] in LINE %d... ", __FUNCTION__, __LINE__) 42 43 const int MAXN = 100000 + 5; 44 45 namespace Math { 46 const int MOD = 998244353; 47 48 IL int add(int a, int b) { 49 a += b; 50 return a >= MOD ? a - MOD : a; 51 } 52 53 template <class ...Args> 54 IL int add(int a, const Args &...args) { 55 a += add(args...); 56 return a >= MOD ? a - MOD : a; 57 } 58 59 IL int sub(int a, int b) { 60 a -= b; 61 return a < 0 ? a + MOD : a; 62 } 63 64 IL int mul(int a, int b) { 65 return (LL)a * b % MOD; 66 } 67 68 template <class ...Args> 69 IL int mul(int a, const Args &...args) { 70 return (LL)a * mul(args...) % MOD; 71 } 72 73 IL int quickPow(int a, int p) { 74 int result = 1; 75 for (; p; p >>= 1, a = mul(a, a)) { 76 if (p & 1) { 77 result = mul(result, a); 78 } 79 } 80 return result; 81 } 82 } 83 84 using namespace Math; 85 86 int fac[MAXN], ifac[MAXN]; 87 88 IL void init(int n) { 89 fac[0] = 1; 90 For(i, 1, n) { 91 fac[i] = mul(fac[i - 1], i); 92 } 93 ifac[n] = quickPow(fac[n], MOD - 2); 94 REP(i, n, 0) { 95 ifac[i] = mul(ifac[i + 1], i + 1); 96 } 97 } 98 99 IL int binom(int n, int m) { 100 return n >= m ? mul(fac[n], ifac[m], ifac[n - m]) : 0; 101 } 102 103 namespace Poly { 104 const int G = 3, G_inv = (MOD + 1) / G, MASK = 18; 105 106 int pos[1 << MASK], root[1 << MASK], root_inv[1 << MASK], len; 107 108 IL void init(int n) { 109 for (; 1 << len <= n; ++ len); 110 FOR(i, 0, 1 << len) { 111 pos[i] = (pos[i >> 1] >> 1) | ((i & 1) << (len - 1)); 112 } 113 int w = quickPow(G, (MOD - 1) >> len); 114 root[0] = 1; 115 FOR(i, 1, 1 << len) { 116 root[i] = mul(root[i - 1], w); 117 } 118 w = quickPow(G_inv, (MOD - 1) >> len); 119 root_inv[0] = 1; 120 FOR(i, 1, 1 << len) { 121 root_inv[i] = mul(root_inv[i - 1], w); 122 } 123 } 124 125 IL void NTT(int *a, int n, int *root) { 126 int shift = __builtin_ctz((1 << len) / n); 127 FOR(i, 0, n) { 128 if (i < pos[i] >> shift) { 129 std::swap(a[i], a[pos[i] >> shift]); 130 } 131 } 132 for (int i = 2; i <= n; i <<= 1) { 133 shift = __builtin_ctz((1 << len) / i); 134 int w = i >> 1; 135 for (int *p = a; p != a + n; p += i) { 136 FOR(j, 0, w) { 137 int x = mul(p[j + w], root[j << shift]); 138 p[j + w] = sub(p[j], x); 139 p[j] = add(p[j], x); 140 } 141 } 142 } 143 } 144 145 IL void DFT(int *a, int n) { 146 NTT(a, n, root); 147 } 148 149 IL void IDFT(int *a, int n) { 150 NTT(a, n, root_inv); 151 int inv = quickPow(n, MOD - 2); 152 FOR(i, 0, n) { 153 a[i] = mul(a[i], inv); 154 } 155 } 156 157 IL void multiply(int *f, int n, int *g, int m, int *result) { 158 int len = 0; 159 for (; 1 << len < n + m; ++ len); 160 static int x[1 << MASK], y[1 << MASK]; 161 std::copy(f, f + n, x); 162 memset(x + n, 0, sizeof(int) * ((1 << len) - n)); 163 std::copy(g, g + m, y); 164 memset(y + m, 0, sizeof(int) * ((1 << len) - m)); 165 memset(result, 0, sizeof(int) << len); 166 DFT(x, 1 << len); 167 DFT(y, 1 << len); 168 FOR(i, 0, 1 << len) { 169 result[i] = mul(x[i], y[i]); 170 } 171 IDFT(result, 1 << len); 172 } 173 } 174 175 int f[MAXN * 4], g[MAXN * 4], h[MAXN * 4]; 176 177 int main() { 178 int D, n, m; 179 scanf("%d%d%d", &D, &n, &m); 180 if (n < m * 2) { 181 puts("0"); 182 exit(0); 183 } 184 if (m * 2 + D - ((D & 1) ^ (n & 1)) <= n) { 185 printf("%d ", quickPow(D, n)); 186 exit(0); 187 } 188 init(D); 189 Poly::init(D << 1); 190 auto F = [&](int k) { 191 return k ? mul((n - m * 2) % 2 ? MOD - 1 : 1, binom(k - 1, n - m * 2)) : 1; 192 }; 193 For(i, 0, D) { 194 f[i] = mul(quickPow(sub(i * 2, D), n), ifac[D - i]); 195 g[i] = mul(F(i), quickPow(2, D - i), ifac[D - i]); 196 } 197 Poly::multiply(f, D + 1, g, D + 1, h); 198 int answer = 0; 199 For(i, D, D * 2) { 200 answer = add(answer, mul((i - D) % 2 ? MOD - 1 : 1, ifac[i - D], h[i])); 201 } 202 printf("%d ", mul(answer, fac[D], quickPow(quickPow(2, D), MOD - 2))); 203 return 0; 204 }
无处安放
提答,不写。
田野
不会。
重复
考虑先取$s$的最长满足任意子串都大于等于等长前缀,任意后缀都大于等长前缀的前缀,这个可以KMP实现。
然后将条件容斥成任意子串都大于等于$s$的串的数量,再取$s$的前驱(一定能取到),大于等于就变成了大于。
现在我们有一个性质:任意合法串和一些形如$s$的前缀加上一个大于$s$下一个字符的字符的串的拼接一一对应。
证明可以通过取最小表示实现,脑补也行。
那么就是一个线性递推了,这个数据范围下求逆更好一些。
1 #include <bits/stdc++.h> 2 3 #define IL __inline__ __attribute__((always_inline)) 4 5 #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i) 6 #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i) 7 #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i) 8 #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i) 9 10 typedef long long LL; 11 12 template <class T> 13 IL bool chkmax(T &a, const T &b) { 14 return a < b ? ((a = b), 1) : 0; 15 } 16 17 template <class T> 18 IL bool chkmin(T &a, const T &b) { 19 return a > b ? ((a = b), 1) : 0; 20 } 21 22 template <class T> 23 IL T mymax(const T &a, const T &b) { 24 return a > b ? a : b; 25 } 26 27 template <class T> 28 IL T mymin(const T &a, const T &b) { 29 return a < b ? a : b; 30 } 31 32 template <class T> 33 IL T myabs(const T &a) { 34 return a > 0 ? a : -a; 35 } 36 37 const int INF = 0X3F3F3F3F; 38 const double EPS = 1E-10, PI = acos(-1.0); 39 40 #define DEBUG(...) fprintf(stderr, __VA_ARGS__) 41 #define OK DEBUG("Passing [%s] in LINE %d... ", __FUNCTION__, __LINE__) 42 43 namespace Math { 44 const int MOD = 998244353; 45 46 IL int add(int a, int b) { 47 a += b; 48 return a >= MOD ? a - MOD : a; 49 } 50 51 template <class ...Args> 52 IL int add(int a, const Args &...args) { 53 a += add(args...); 54 return a >= MOD ? a - MOD : a; 55 } 56 57 IL int sub(int a, int b) { 58 a -= b; 59 return a < 0 ? a + MOD : a; 60 } 61 62 IL int mul(int a, int b) { 63 return (LL)a * b % MOD; 64 } 65 66 template <class ...Args> 67 IL int mul(int a, const Args &...args) { 68 return (LL)a * mul(args...) % MOD; 69 } 70 71 IL int quickPow(int a, int p) { 72 int result = 1; 73 for (; p; p >>= 1, a = mul(a, a)) { 74 if (p & 1) { 75 result = mul(result, a); 76 } 77 } 78 return result; 79 } 80 } 81 82 using namespace Math; 83 84 const int MAXN = 100000 + 5, LOG = 18, G = 3, G_inv = 332748118, INV_2 = 499122177; 85 86 int inv[1 << LOG]; 87 88 IL void init(int n) { 89 inv[1] = 1; 90 For(i, 2, n) { 91 inv[i] = mul(inv[MOD % i], MOD - MOD / i); 92 } 93 } 94 95 namespace Poly { 96 int pos[1 << LOG], root[1 << LOG], root_inv[1 << LOG], len; 97 98 IL void init(int n) { 99 for (; 1 << len < n; ++ len); 100 FOR(i, 0, 1 << len) { 101 pos[i] = (pos[i >> 1] >> 1) | ((i & 1) << (len - 1)); 102 } 103 int w = quickPow(G, (MOD - 1) >> len); 104 root[0] = 1; 105 FOR(i, 1, 1 << len) { 106 root[i] = mul(root[i - 1], w); 107 } 108 w = quickPow(G_inv, (MOD - 1) >> len); 109 root_inv[0] = 1; 110 FOR(i, 1, 1 << len) { 111 root_inv[i] = mul(root_inv[i - 1], w); 112 } 113 } 114 115 IL void NTT(int *a, int n, int *root) { 116 int shift = __builtin_ctz((1 << len) / n); 117 FOR(i, 0, n) { 118 if (i > pos[i] >> shift) { 119 std::swap(a[i], a[pos[i] >> shift]); 120 } 121 } 122 for (int i = 2; i <= n; i <<= 1) { 123 int k = i >> 1; 124 shift = __builtin_ctz((1 << len) / i); 125 for (int *p = a; p != a + n; p += i) { 126 FOR(j, 0, k) { 127 int temp = mul(p[j + k], root[j << shift]); 128 p[j + k] = sub(p[j], temp); 129 p[j] = add(p[j], temp); 130 } 131 } 132 } 133 } 134 135 IL void DFT(int *a, int n) { 136 NTT(a, n, root); 137 } 138 139 IL void IDFT(int *a, int n) { 140 NTT(a, n, root_inv); 141 int inv_n = quickPow(n, MOD - 2); 142 FOR(i, 0, n) { 143 a[i] = mul(a[i], inv_n); 144 } 145 } 146 147 IL void multiply(int *a, int n, int *b, int m, int *result) { 148 int len = 0; 149 for (; 1 << len < n + m; ++ len); 150 static int x[1 << LOG], y[1 << LOG]; 151 std::copy(a, a + n, x); 152 memset(x + n, 0, ((1 << len) - n) * sizeof (int)); 153 std::copy(b, b + m, y); 154 memset(y + m, 0, ((1 << len) - m) * sizeof (int)); 155 memset(result, 0, (1 << len) * sizeof (int)); 156 DFT(x, 1 << len); 157 DFT(y, 1 << len); 158 FOR(i, 0, 1 << len) { 159 result[i] = mul(x[i], y[i]); 160 } 161 IDFT(result, 1 << len); 162 memset(result + n + m - 1, 0, ((1 << len) - n - m + 1) * sizeof (int)); 163 } 164 165 void inverse(int *f, int *g, int t) { 166 if (t == 1) { 167 g[0] = quickPow(f[0], MOD - 2); 168 return; 169 } 170 inverse(f, g, (t + 1) >> 1); 171 int len = 0; 172 for (; 1 << len < t << 1; ++ len); 173 static int temp[1 << LOG]; 174 std::copy(f, f + t, temp); 175 memset(temp + t, 0, ((1 << len) - t) * sizeof (int)); 176 DFT(temp, 1 << len); 177 DFT(g, 1 << len); 178 FOR(i, 0, 1 << len) { 179 g[i] = mul(g[i], sub(2, mul(temp[i], g[i]))); 180 } 181 IDFT(g, 1 << len); 182 memset(g + t, 0, ((1 << len) - t) * sizeof (int)); 183 } 184 185 IL void reverse(int *f, int n) { 186 std::reverse(f, f + n); 187 } 188 189 IL void inc(int *f, int *g, int n, int *result) { 190 FOR(i, 0, n) { 191 result[i] = add(f[i], g[i]); 192 } 193 } 194 195 IL void dec(int *f, int *g, int n, int *result) { 196 FOR(i, 0, n) { 197 result[i] = sub(f[i], g[i]); 198 } 199 } 200 201 IL void divide(int *f, int n, int *g, int m, int *q, int *r) { 202 reverse(f, n), reverse(g, m); 203 int len = 0; 204 for (; 1 << len < n + m; ++ len); 205 static int temp[1 << LOG]; 206 memset(temp, 0, (1 << len) * sizeof (int)); 207 inverse(g, temp, n - m + 1); 208 multiply(f, n - m + 1, temp, n - m + 1, q); 209 reverse(q, n - m + 1); 210 reverse(f, n), reverse(g, m); 211 multiply(g, m, q, n - m + 1, temp); 212 dec(f, temp, n, r); 213 } 214 215 IL void derive(int *f, int n, int *result) { 216 FOR(i, 0, n - 1) { 217 result[i] = mul(f[i + 1], i + 1); 218 } 219 } 220 221 IL void integrate(int *f, int n, int *result) { 222 Rep(i, n, 1) { 223 result[i] = mul(f[i - 1], inv[i]); 224 } 225 result[0] = 0; 226 } 227 228 IL void ln(int *f, int *g, int n) { 229 int len = 0; 230 for (; 1 << len < n; ++ len); 231 static int temp1[1 << LOG], temp2[1 << LOG]; 232 memset(temp1, 0, (1 << len) * sizeof (int)); 233 memset(temp2, 0, (1 << len) * sizeof (int)); 234 inverse(f, temp1, n); 235 derive(f, n, temp2); 236 multiply(temp1, n, temp2, n - 1, g); 237 integrate(g, n - 1, g); 238 } 239 240 void exp(int *f, int *g, int t) { 241 if (t == 1) { 242 g[0] = 1; 243 return; 244 } 245 exp(f, g, (t + 1) >> 1); 246 int len = 0; 247 for (; 1 << len < t << 1; ++ len); 248 static int temp1[1 << LOG], temp2[1 << LOG]; 249 memset(temp1, 0, (1 << len) * sizeof (int)); 250 ln(g, temp1, t); 251 std::copy(f, f + t, temp2); 252 memset(temp2 + t, 0, ((1 << len) - t) * sizeof (int)); 253 ++ temp2[0]; 254 dec(temp2, temp1, t, temp2); 255 multiply(temp2, t, g, t, g); 256 memset(g + t, 0, ((1 << len) - t) * sizeof (int)); 257 } 258 259 void sqrt(int *f, int *g, int t) { 260 if (t == 1) { 261 g[0] = 1; 262 return; 263 } 264 sqrt(f, g, (t + 1) >> 1); 265 int len = 0; 266 for (; 1 << len < t << 1; ++ len); 267 static int temp[1 << LOG]; 268 memset(temp, 0, (1 << len) * sizeof (int)); 269 inverse(g, temp, t); 270 multiply(f, t, temp, t, temp); 271 inc(g, temp, t, g); 272 FOR(i, 0, t) { 273 g[i] = mul(g[i], INV_2); 274 } 275 } 276 277 int pre_work[LOG][MAXN * 8]; 278 279 void decompositionNTT(int *a, int level, int l, int r) { 280 if (l + 1 >= r) { 281 pre_work[level][l << 1] = sub(0, a[l]); 282 pre_work[level][l << 1 | 1] = 1; 283 return; 284 } 285 int mid = (l + r) >> 1; 286 decompositionNTT(a, level + 1, l, mid); 287 decompositionNTT(a, level + 1, mid, r); 288 static int temp[1 << LOG]; 289 multiply(pre_work[level + 1] + (l << 1), mid - l + 1, pre_work[level + 1] + (mid << 1), r - mid + 1, temp); 290 std::copy(temp, temp + r - l + 1, pre_work[level] + (l << 1)); 291 } 292 293 int result_eval[LOG][1 << LOG]; 294 295 void getEvaluation(int *f, int *g, int level, int l, int r) { 296 static int temp[1 << LOG]; 297 if (level) { 298 divide(f, ((r - l) << 1) + 1, pre_work[level] + (l << 1), r - l + 1, temp, result_eval[level] + l); 299 } else { 300 std::copy(f + l, f + r, result_eval[level] + l); 301 } 302 if (l + 1 >= r) { 303 g[l] = result_eval[level][l]; 304 return; 305 } 306 int mid = (l + r) >> 1; 307 getEvaluation(result_eval[level] + l, g, level + 1, l, mid); 308 getEvaluation(result_eval[level] + l, g, level + 1, mid, r); 309 } 310 311 IL void evaluate(int *a, int *f, int n, int *g) { 312 decompositionNTT(a, 0, 0, n); 313 getEvaluation(f, g, 0, 0, n); 314 } 315 316 void decompositionNTT(int *f, int *g, int level, int l, int r) { 317 if (l + 1 >= r) { 318 f[l] = g[l]; 319 return; 320 } 321 int mid = (l + r) >> 1; 322 decompositionNTT(f, g, level + 1, l, mid); 323 decompositionNTT(f, g, level + 1, mid, r); 324 static int temp1[1 << LOG], temp2[1 << LOG]; 325 multiply(f + l, mid - l, pre_work[level + 1] + (mid << 1), r - mid + 1, temp1); 326 multiply(f + mid, r - mid, pre_work[level + 1] + (l << 1), mid - l + 1, temp2); 327 FOR(i, l, r) { 328 f[i] = add(temp1[i - l], temp2[i - l]); 329 } 330 } 331 332 IL void interpolate(int *x, int *y, int n, int *f) { 333 decompositionNTT(x, 0, 0, n); 334 static int temp1[1 << LOG], temp2[1 << LOG]; 335 std::copy(pre_work[0], pre_work[0] + n + 1, temp1); 336 derive(temp1, n + 1, temp1); 337 getEvaluation(temp1, temp2, 0, 0, n); 338 FOR(i, 0, n) { 339 temp2[i] = mul(y[i], quickPow(temp2[i], MOD - 2)); 340 } 341 decompositionNTT(f, temp2, 0, 0, n); 342 } 343 } 344 345 char str[MAXN]; 346 int nxt[MAXN], f[MAXN], g[MAXN]; 347 348 int main() { 349 int m; 350 scanf("%d", &m); 351 init(m); 352 Poly::init(m << 1); 353 scanf("%s", str + 1); 354 int n = strlen(str + 1); 355 For(i, 2, n) { 356 int cur = i - 1; 357 while (nxt[cur] && str[nxt[cur] + 1] != str[i]) { 358 cur = nxt[cur]; 359 } 360 nxt[i] = nxt[cur] + (str[nxt[cur] + 1] == str[i]); 361 } 362 for (int i = 1; i < n; ++ i) { 363 if (str[i + 1] < str[nxt[i] + 1]) { 364 n = i; 365 } 366 } 367 while (nxt[n]) { 368 -- n; 369 } 370 if (n > m) { 371 n = m; 372 } else { 373 -- str[n]; 374 } 375 f[0] = 1; 376 For(i, 1, n) { 377 f[i] = sub(str[i], 'z'); 378 } 379 Poly::inverse(f, g, m + 1); 380 int answer = sub(quickPow(26, m), g[m]); 381 For(i, 2, m) { 382 answer = add(answer, mul(i - 1, f[i], g[m - i])); 383 } 384 printf("%d ", answer); 385 return 0; 386 }
氪金手游
先考虑如果树是一棵外向树怎么做:令$f_{i,j}$为$i$节点子树权值和为$j$时的概率,转移类似于背包。
问题是现在有反向边,那我们可以把它容斥掉(无视这条边的答案减去这条边反向的答案),转移时乘上一个-1的容斥系数即可。
1 #include <bits/stdc++.h> 2 3 #define IL __inline__ __attribute__((always_inline)) 4 5 #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i) 6 #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i) 7 #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i) 8 #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i) 9 10 typedef long long LL; 11 12 template <class T> 13 IL bool chkmax(T &a, const T &b) { 14 return a < b ? ((a = b), 1) : 0; 15 } 16 17 template <class T> 18 IL bool chkmin(T &a, const T &b) { 19 return a > b ? ((a = b), 1) : 0; 20 } 21 22 template <class T> 23 IL T mymax(const T &a, const T &b) { 24 return a > b ? a : b; 25 } 26 27 template <class T> 28 IL T mymin(const T &a, const T &b) { 29 return a < b ? a : b; 30 } 31 32 template <class T> 33 IL T myabs(const T &a) { 34 return a > 0 ? a : -a; 35 } 36 37 const int INF = 0X3F3F3F3F; 38 const double EPS = 1E-8, PI = acos(-1.0); 39 40 #define DEBUG(...) fprintf(stderr, __VA_ARGS__) 41 #define OK DEBUG("Passing [%s] in LINE %d... ", __FUNCTION__, __LINE__) 42 43 namespace Math { 44 const int MOD = 998244353; 45 46 IL int add(int a, int b) { 47 a += b; 48 return a >= MOD ? a - MOD : a; 49 } 50 51 template <class ...Args> 52 IL int add(int a, const Args &...args) { 53 a += add(args...); 54 return a >= MOD ? a - MOD : a; 55 } 56 57 IL int sub(int a, int b) { 58 a -= b; 59 return a < 0 ? a + MOD : a; 60 } 61 62 IL int mul(int a, int b) { 63 return (LL)a * b % MOD; 64 } 65 66 template <class ...Args> 67 IL int mul(int a, const Args &...args) { 68 return (LL)a * mul(args...) % MOD; 69 } 70 71 IL int quickPow(int a, int p) { 72 int result = 1; 73 for (; p; p >>= 1, a = mul(a, a)) { 74 if (p & 1) { 75 result = mul(result, a); 76 } 77 } 78 return result; 79 } 80 } 81 82 using namespace Math; 83 84 const int MAXN = 1000 + 5; 85 86 int a[MAXN][4], inv[MAXN * 3]; 87 88 struct Tree { 89 int hed[MAXN], nxt[MAXN * 2], to[MAXN * 2], fa[MAXN], size[MAXN], f[MAXN][MAXN * 3], g[MAXN][MAXN * 3], cnt; 90 bool dir[MAXN * 2]; 91 92 void addEdge(int u, int v, bool d) { 93 ++ cnt; 94 dir[cnt] = d; 95 to[cnt] = v; 96 nxt[cnt] = hed[u]; 97 hed[u] = cnt; 98 } 99 100 void DFS(int u) { 101 size[u] = 1; 102 For(i, 1, 3) { 103 f[u][i] = a[u][i]; 104 } 105 for (int e = hed[u]; e; e = nxt[e]) { 106 int v = to[e]; 107 if (v != fa[u]) { 108 fa[v] = u; 109 DFS(v); 110 For(i, 1, (size[u] + size[v]) * 3) { 111 g[u][i] = 0; 112 } 113 if (dir[e]) { 114 For(i, 1, size[u] * 3) { 115 For(j, 1, size[v] * 3) { 116 g[u][i + j] = add(g[u][i + j], mul(f[u][i], f[v][j], i, inv[i + j])); 117 } 118 } 119 } else { 120 For(i, 1, size[u] * 3) { 121 For(j, 1, size[v] * 3) { 122 g[u][i + j] = sub(g[u][i + j], mul(f[u][i], f[v][j], i, inv[i + j])); 123 g[u][i] = add(g[u][i], mul(f[u][i], f[v][j])); 124 } 125 } 126 } 127 size[u] += size[v]; 128 std::copy(g[u] + 1, g[u] + size[u] * 3 + 1, f[u] + 1); 129 } 130 } 131 } 132 } T; 133 134 int main() { 135 int n; 136 scanf("%d", &n); 137 inv[1] = 1; 138 For(i, 2, n * 3) { 139 inv[i] = mul(inv[MOD % i], MOD - MOD / i); 140 } 141 For(i, 1, n) { 142 scanf("%d%d%d", &a[i][1], &a[i][2], &a[i][3]); 143 int s = quickPow(a[i][1] + a[i][2] + a[i][3], MOD - 2); 144 a[i][1] = mul(a[i][1], s), a[i][2] = mul(a[i][2], s), a[i][3] = mul(a[i][3], s); 145 } 146 For(i, 2, n) { 147 int u, v; 148 scanf("%d%d", &u, &v); 149 T.addEdge(u, v, 1); 150 T.addEdge(v, u, 0); 151 } 152 T.DFS(1); 153 int answer = 0; 154 For(i, 1, n * 3) { 155 answer = add(answer, T.f[1][i]); 156 } 157 printf("%d ", answer); 158 return 0; 159 }