• CTS2019 题解


    随机立方体

    设$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 }
    View Code

     珍珠

    考虑同一个权值至多贡献一个奇数,那么至多有$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 }
    View Code

     无处安放

    提答,不写。

    田野

    不会。

    重复

    考虑先取$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 }
    View Code

     氪金手游

    先考虑如果树是一棵外向树怎么做:令$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 }
    View Code
  • 相关阅读:
    你应该掌握的——树和二叉树
    nyist oj 63(二叉树)
    非递归遍历二叉树的四种策略先序、中序、后序和层序
    学习的四种境界
    nyist oj 467 (中缀式变后缀式)
    二叉平衡树
    nyist OJ 35 (表达式求值)
    线索二叉树
    二叉树的三种遍历方法(递归和非递归)
    算法学习之路
  • 原文地址:https://www.cnblogs.com/sjkmost/p/10950638.html
Copyright © 2020-2023  润新知