Titulo
Analizando
Considere cómo juzgar si una secuencia satisface la condición. Deje que $ c_i $ represente el número de ocurrencias del número $ i $, luego: $$ \ sum_ {i = 1} ^ D \ left \ lfloor \ frac {c_i} {2} \ right \ rfloor \ geqslant m \\ \ sum_ {i = 1} ^ D \ frac {c_i- (c_i \% 2)} {2} \ geqslant m \\ n- \ sum_ {i = 1} ^ D (c_i \% 2) \ geqslant 2m \\ \ sum_ {i = 1} ^ D (c_i \% 2) \ leqslant n-2m $$
Cuando $ n-2m <0 $, salida $ 0 $; cuando $ n-2m \ geqslant D $, salida $ D ^ n $
Supongamos que $ g_i $ significa que exactamente el número de ocurrencias de $ i $ es impar, y $ f_i $ significa que al menos las ocurrencias de $ i $ son impares, y $ f_i = \ sum_ {j = i} \ binom {j} { i} g_j $
Si encontramos $ f $ entonces podemos encontrar $ g $ por inversión binomial, por lo que ahora necesitamos encontrar una manera de encontrar $ f $
Considere generar funciones, deje $ A (x) = \ sum_ {i = 0} ^ {\ infty} [i \% 2 == 1] x ^ i = \ frac {e ^ xe ^ {-x}} {2 } $, $ B (x) = \ sum_ {i = 0} ^ {\ infty} x ^ i = e ^ x $
钦 定 有 $ i $ 个数 出现 奇 数次 , 剩下 的 数 出现 任意 次数 , 则 有 : $$ \ begin {align *} f_i & = \ binom {D} {i} n! [X ^ n] A ^ iB ^ {Di} \\ & = \ binom {D} {i} n! [X ^ n] (\ frac {e ^ xe ^ {- x}} {2}) ^ ie ^ {(Di) x} \ \ & = \ frac {D!} {i! (Di)!} n! * \ frac {1} {2 ^ i} [x ^ n] \ sum_ {j = 0} ^ i \ binom {i} { j} (- 1) ^ {ij} e ^ {jx} e ^ {- (ij) x} e ^ {(Di) x} \\ & = \ frac {D! n!} {i! (Di) ! 2 ^ i} * [x ^ n] \ sum_ {j = 0} ^ i \ binom {i} {j} (- 1) ^ {ij} e ^ {(D-2i + 2j) x} \\ & = \ frac {D! n!} {i! (Di)! 2 ^ i} \ sum_ {j = 0} ^ i \ frac {i!} {j! (ij)!} * (- 1) ^ {ij} * \ frac {(D-2i + 2j) ^ n} {n!} \\ & = \ frac {D!} {(Di)! 2 ^ i} \ sum_ {j = 0} ^ i \ frac {(- 1) ^ {ij} (D-2i + 2j) ^ n} {(ij)!} * \ frac {1} {j!} \ end {align *} $$
Convolucionar para encontrar $ f $
然后 二项式 反演 : $$ \ begin {align *} g_i & = \ sum_ {j = i} ^ D (-1) ^ {ji} \ binom {j} {i} f_j \\ & = \ frac { 1} {i!} \ Sum_ {j = i} ^ D \ frac {(- 1) ^ {ji}} {(ji)!} * J! * F_j \ end {align *} $$
La respuesta final es: $ Ans = \ sum_ {i = 0} ^ {n-2m} g_i $$
$ O (D \ log D) $
Código:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> usando el espacio de nombres std; typedef largo largo ll; const int maxn = 200005 , mod = 998244353 , g = 3 ; int add ( int x, int y) { volver x + y <mod? x + y: x + y - mod; } int rdc ( int x, int y) { return x - y < 0? x - y + mod: x - y; } ll qpow (ll x, int y) { ll ret = 1 ; mientras (y) { si (y & 1 ) ret = ret * x% mod; x = x * x% mod; y >> = 1 ; } volver a la derecha; } int D, n, m; int lim, bit, rev [maxn << 1 ]; ll fac [maxn], fnv [maxn]; ll ginv, f [maxn << 1 ], A [maxn << 1 ], B [maxn << 1 ]; void init () { ginv = qpow (g, mod - 2 ); fac [ 0 ] = 1 ; para ( int i = 1 ; i <= D; ++ i) fac [i] = fac [i- 1 ] * i% mod; fnv [D] = qpow (fac [D], mod - 2 ); para ( int i = D - 1 ; i> = 0 ; - i) fnv [i] = fnv [i + 1 ] * (i + 1 )% mod; } nulo NTT_init ( int x) { lim = 1 ; bit = 0 ; mientras que (lim <= x) { lim << = 1 ; ++ bit; } para ( int i = 1 ; i <lim; ++ i) rev [i] = (rev [i >> 1 ] >> 1 ) | ((i & 1 ) << (bit - 1 )); } NTT nulo (ll * x, int y) { para ( int i = 1 ; i <lim; ++ i) if (i < rev [i]) swap (x [i], x [rev [i]]); ll wn, w, u, v; para ( int i = 1 ; i <lim; i << = 1 ) { wn = qpow ((y == 1 )? g: ginv, (mod - 1 ) / (i << 1 )); para ( int j = 0 ; j <lim; j + = (i << 1 )) { w = 1 ; para ( int k = 0 ; k <i; ++ k) { u = x [j + k]; v = x [j + k + i] * w% mod; x [j + k] = sumar (u, v); x [j + k + i] = rdc (u, v); w = w * wn% mod; } } } si (y == - 1 ) { ll linv = qpow (lim, mod - 2 ); para ( int i = 0 ; i <lim; ++ i) x [i] = x [i] * linv% mod; } } int main () { scanf ( " % d% d% d " , & D, & n, & m); si (n - 2 * m < 0 ) { printf ( " 0 " ); devuelve 0 ; } si (n - 2 * m> = D) { printf ( " % lld " , qpow (D, n)); devuelve 0 ; } en eso(); para ( int i = 0 ; i <= D; ++ i) { A [i] = qpow (rdc (D, 2 * i), n) * fnv [i]% mod; A [i] = ((i & 1 )? Rdc ( 0 , A [i]): A [i]); B [i] = fnv [i]; } NTT_init (D << 1 ); NTT (A, 1 ); NTT (B, 1 ); para ( int i = 0 ; i <lim; ++ i) A [i] = A [i] * B [i]% mod; NTT (A, - 1 ); para ( int i = 0 ; i <= D; ++ i) A [i] = ((A [i] * fac [D]% mod) * qpow (qpow ( 2 , i), mod - 2 )% mod) * fnv [Di]% mod; para ( int i = D + 1 ; i <lim; ++ i) A [i] = 0 ; para ( int i = 0 ; i <= D; ++ i) { A [i] = A [i] * fac [i]% mod; f [D -i] = ((i & 1 )? rdc ( 0 , fnv [i]): fnv [i]); } NTT (A, 1 ); NTT (f, 1 ); para ( int i = 0 ; i <lim; ++ i) f [i] = f [i] * A [i]% mod; NTT (f, - 1 ); int ans = 0 ; para ( int i = 0 ; i <= n - 2 * m; ++ i) ans = add (ans, f [D + i] * fnv [i]% mod); printf ( " % d " , ans); devuelve 0 ; }