вопросы для лица
Решимость
Рассмотрим, как определить, удовлетворяет ли последовательность условию. Пусть $ c_i $ представляет число вхождений числа $ i $, затем: $$ \ 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 $$
Когда $ n-2m <0 $, выведите $ 0 $, когда $ n-2m \ geqslant D $, выведите $ D ^ n $
Пусть $ g_i $ означает, что ровно число вхождений $ i $ нечетно, а $ f_i $ означает, что хотя бы $ i $ вхождений нечетно, а $ f_i = \ sum_ {j = i} \ binom {j} { я} g_j $
Если мы найдем $ f $, то сможем найти $ g $ путем биномиальной инверсии, поэтому теперь нам нужно найти способ найти $ f $
Рассмотрим создание функций, пусть $ 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 $ 个数 出现 奇 数次, 剩下 的 数 出现 任意 次数, 则 有: $$ \ {начать выравнивание *} f_i & = \ БИНОМ {D} {г} п [х ^ п] А ^ И.Б. ^ {Di} \\ & = \ БИНОМ {D} {г} п [х ^ п] (\ гидроразрыва {е ^ х ^ {- х}} {2})! ^ т ^ {(Di) х} \ \ & = \ гидроразрыва {D!} {я! (Ди)!} п! * \ гидроразрыва {1} {2 ^ я} [х ^ п] \ sum_ {J = 0} ^ я \ БИНОМ {я} { J} (- 1) ^ {IJ} е ^ {JX} е ^ {-! (Ij) х} е ^ {(Di) х} \\ & = \ гидроразрыва {D} {п я (Di) ! 2 ^ я} * [х ^ п] \ sum_ {J = 0} ^ я \ БИНОМ {я} {J} (- 1) ^ {IJ} е ^ {(D-2i + 2j) х} \\ & = \ гидроразрыва {D п!} {я (Di) 2 ^ я!} \ sum_ {j = 0} ^ я \ гидроразрыва {я!} * {j (Ij)!} (- 1) ^ {IJ} * \ гидроразрыва {(D-2i + 2j) ^ п} {п!} \\ & = \ гидроразрыва {D!} {(Di)! 2 ^ я} \ sum_ {j = 0} ^ я \ гидроразрыва {(- 1) ^ {IJ} (D-2i + 2j) ^ п} {! (Ij)} * \ гидроразрыва {1} {! J} \ конец {выравнивание *} $$
Свернуть, чтобы найти $ f $
然后 二项式 反演: $$ \ {начать выравнивание *} g_i & = \ sum_ {J = я} ^ D (-1) ^ {ц} \ БИНОМ {J} {} я f_j \\ & = \ гидроразрыва { 1} {г} \ sum_ {j = я} ^ D \ гидроразрыва {! (- 1) ^ {ц}!} {(ц)} * J * f_j \ конец {выравнивание *} $$
Окончательный ответ: $ Ans = \ sum_ {i = 0} ^ {n-2m} g_i $$
$ O (D \ log D) $
Код:
#include <cstdio> #include <iostream> #include <алгоритм> #include <cstring> с использованием пространства имен std; typedef long long ll; const int maxn = 200005 , mod = 998244353 , g = 3 ; int add ( int x, int y) { вернуть x + y <mod? х + у: х + у - мод; } int rdc ( int x, int y) { return x - y < 0? х - у + мод: х - у; } ll qpow (ll x, int y) { ll ret = 1 ; while (y) { if (y & 1 ) ret = ret * x% mod; х = х * х% мод; у >> = 1 ; } return ret; } 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 ; for ( int i = 1 ; i <= D; ++ i) fac [i] = fac [i- 1 ] * i% mod; fnv [D] = qpow (fac [D], mod - 2 ); для ( int i = D - 1 ; i> = 0 ; - i) fnv [i] = fnv [i + 1 ] * (i + 1 )%мод; } void NTT_init ( int x) { lim = 1 ; бит = 0 ; while (lim <= x) { lim << = 1 ; ++ бит; } for ( int i = 1 ; i <lim; ++ i) rev [i] = (rev [i >> 1 ] >> 1 ) | ((i & 1 ) << (бит - 1 )); } void NTT (ll * x, int y) { for ( int i = 1 ; i <lim; ++ i) if (i < rev [i]) swap (x [i], x [rev [i]]); ll wn, w, u, v; for ( int i = 1 ; i <lim; i << = 1 ) { wn = qpow ((y == 1 )? g: ginv, (mod - 1 ) / (i << 1 )); для ( int j = 0 ; j <lim; j + = (i << 1 )) { w = 1 ; для( int k = 0 ; k <i; ++ k) { u = x [j + k]; v = x [j + k + i] * w% mod; x [j + k] = add (u, v); x [j + k + i] = rdc (u, v); w = w * wn% mod; } } } if (y == - 1 ) { ll linv = qpow (lim, mod - 2 ); для ( int i = 0 ; i <lim; ++ i) x [i] = x [i] * linv% mod; } } int main () { scanf ( " % d% d% d " , & D, & n, & m); if (n - 2 * m < 0 ) { printf ( " 0 " ); вернуть 0 ; } if (n - 2 * m> = D) { printf ( " % lld " , qpow (D, n)); вернуть 0 ; } init (); для ( 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 ); для ( int i = 0 ; i <lim; ++ i) A [i] = A [i] * B [i]% mod; NTT (A, - 1 ); для ( int i = 0 ; i <= D; ++ i) A [i] = ((A [i] * fac [D]% mod) * qpow (qpow ( 2 , i), mod - 2 )% mod) * fnv [Di]% mod; для ( int i = D + 1 ; i <lim; ++ i) A [i] = 0 ; for ( int i = 0 ; i <= D; ++ i) { A [i] = A [i] * fac [i]% mod; f [D 1-i] = ((i & )? rdc ( 0 , fnv [i]): fnv [i]); } NTT (A, 1 ); NTT (f, 1 ); for ( int i = 0 ; i <lim; ++ i) f [i] = f [i] * A [i]% mod; NTT (f, - 1 ); int ans = 0 ; for ( int i = 0 ; i <= n - 2 * m; ++ i) ans = add (ans, f [D + i] * fnv [i]% mod); printf ( " % d " , ans); вернуть 0 ; }