Comet 67E: ffort
题目传送门:Comet 67E。 用了个傻逼做法 A 了这题,欢迎观赏睿智做法! 题意简述:题目说得很清楚了(这次是我不想写了)。 题解:为了方便,令 (m) 为敌人数,(n) 为己方士兵种数。设 (mathbf{Ans}) 为答案,则有: [begin{aligned}mathbf{Ans}&=sum_{a=1}^{infty}([x^a]G)cdotbinom{a-1}{m-1}&=sum_{a=0}^{infty}!left([x^{a}]dfrac{G}{x}right)!cdotbinom{a}{hat m}&=frac{1}{hat m!}sum_{i=0}^{infty}([x^i]F)i^{underline{hat m}}end{aligned}] 意即枚举 (a) 为打出的伤害数,则将这些伤害分配给敌人的方法数为 (dbinom{a-1}{m-1})。 其中 (G) 为给己方士兵分配伤害的方案数的 (mathbf{OGF}),即 (displaystyle G=prod_{i=1}^{n}left[mathbf{OGF}left{0,underset{b_i}{underbrace{1,ldots,1}}right}right]^{a_i})。 则 ([x^a]G) 就为将伤害分配给己方士兵的方案数。 接下来令 (hat m=m-1),(F=dfrac{G}{x}),变换求和指标并提出 (dfrac{1}{hat m!}),留下下降幂形式。 下降幂经常出现在多次求导后的多项式中,即 (displaystyle f^{(k)}(x)=sum_{i=k}^{infty}f_ii^{underline{k}}cdot x^{i-k})。 那么 (displaystylesum_{i=0}^{infty}f_ii^{underline{hat m}}=f^{(hat m)}(1))。 据此,则有: [mathbf{Ans}=frac{1}{hat m!}F^{(m)}(1)] 考虑 (displaystyle F=frac{1}{x}prod_{i=1}^{n}left[mathbf{OGF}left{0,1}}right}right]^{a_i}) 的 (hat m) 阶导:
令 (f_i=mathbf{OGF}left{0,1}}right}) ,特别地 (f_0=dfrac{1}{x}),(a_0=1),那么有 (displaystyle F=prod_{i=0}^{n}f_i^{a_i})。 于是: [begin{aligned}mathbf{Ans}&=frac{1}{hat m}F^{(m)}(1)&=frac{1}{hat m}left(hat m!left[z^{hat m}right]prod_{i=0}^{n}left(sum_{j=0}^{infty}frac{f_i^{(j)}}{j!}z^{j}right)^{a_i}right)(1)&=[z^m]prod_{i=0}^{n}left(sum_{j=0}^{infty}frac{f_i^{(j)}(1)}{j!}z^jright)^{a_i}end{aligned}] 因为 (ntimes mle 10^5),所以后面只要算出 (dfrac{f_i^{(j)}(1)}{j!})((0le ile n),(0le jle m)),然后多项式快速幂暴力乘即可。 接下来考虑如何计算 (dfrac{f_i^{(j)}(1)}{j!}): 对于 (f_0=dfrac{1}{x}),有 (left(dfrac{1}{x}right)^{(k)}(1)=(-1)^kk!),所以 (dfrac{f_0^{(j)}(1)}{j!}=(-1)^j)。 对于 (f_i=mathbf{OGF}left{0,1}}right}),稍加推导可以得到:
那么这题就做完了,代码如下,复杂度 (mathcal O(nmlog m)): #include <cstdio> #include <algorithm> typedef long long LL; const int Mod = 998244353; const int G = 3,iG = 332748118; const int MS = 1 << 19; inline int qPow(int b,int e) { int a = 1; for (; e; e >>= 1,b = (LL)b * b % Mod) if (e & 1) a = (LL)a * b % Mod; return a; } inline int gInv(int b) { return qPow(b,Mod - 2); } int Inv[MS],Fac[MS],iFac[MS]; inline void Init(int N) { Fac[0] = 1; for (int i = 1; i < N; ++i) Fac[i] = (LL)Fac[i - 1] * i % Mod; iFac[N - 1] = gInv(Fac[N - 1]); for (int i = N - 1; i >= 1; --i) iFac[i - 1] = (LL)iFac[i] * i % Mod; for (int i = 1; i < N; ++i) Inv[i] = (LL)Fac[i - 1] * iFac[i] % Mod; } inline int Binom(int N,int M) { if (M < 0 || M > N) return 0; return (LL)Fac[N] * iFac[M] % Mod * iFac[N - M] % Mod; } int Sz,InvSz,R[MS]; inline int getB(int N) { int Bt = 0; while (1 << Bt < N) ++Bt; return Bt; } inline void InitFNTT(int N) { int Bt = getB(N); if (Sz == (1 << Bt)) return ; Sz = 1 << Bt,InvSz = Mod - (Mod - 1) / Sz; for (int i = 1; i < Sz; ++i) R[i] = R[i >> 1] >> 1 | (i & 1) << (Bt - 1); } inline void FNTT(int *A,int Ty) { for (int i = 0; i < Sz; ++i) if (R[i] < i) std::swap(A[R[i]],A[i]); for (int j = 1,j2 = 2; j < Sz; j <<= 1,j2 <<= 1) { int wn = qPow(~Ty ? G : iG,(Mod - 1) / j2),w,X,Y; for (int i = 0,k; i < Sz; i += j2) { for (k = 0,w = 1; k < j; ++k,w = (LL)w * wn % Mod) { X = A[i + k],Y = (LL)w * A[i + j + k] % Mod; A[i + k] -= (A[i + k] = X + Y) >= Mod ? Mod : 0; A[i + j + k] += (A[i + j + k] = X - Y) < 0 ? Mod : 0; } } } if (!~Ty) for (int i = 0; i < Sz; ++i) A[i] = (LL)A[i] * InvSz % Mod; } inline void PolyConv(int *_A,int N,int *_B,int M,int *_C) { static int A[MS],B[MS]; InitFNTT(N + M - 1); for (int i = 0; i < N; ++i) A[i] = _A[i]; for (int i = N; i < Sz; ++i) A[i] = 0; for (int i = 0; i < M; ++i) B[i] = _B[i]; for (int i = M; i < Sz; ++i) B[i] = 0; FNTT(A,1),FNTT(B,1); for (int i = 0; i < Sz; ++i) A[i] = (LL)A[i] * B[i] % Mod; FNTT(A,-1); for (int i = 0; i < N + M - 1; ++i) _C[i] = A[i]; } inline void PolyInv(int *_A,int *_B) { static int A[MS],B[MS],tA[MS],tB[MS]; for (int i = 0; i < N; ++i) A[i] = _A[i]; for (int i = N,B = getB(N); i < 1 << B; ++i) A[i] = 0; B[0] = gInv(A[0]); for (int L = 1; L < N; L <<= 1) { int L2 = L << 1,L4 = L << 2; InitFNTT(L4); for (int i = 0; i < L2; ++i) tA[i] = A[i]; for (int i = L2; i < Sz; ++i) tA[i] = 0; for (int i = 0; i < L; ++i) tB[i] = B[i]; for (int i = L; i < Sz; ++i) tB[i] = 0; FNTT(tA,FNTT(tB,1); for (int i = 0; i < Sz; ++i) tB[i] = tB[i] * (2 - (LL)tA[i] * tB[i] % Mod + Mod) % Mod; FNTT(tB,-1); for (int i = 0; i < L2; ++i) B[i] = tB[i]; } for (int i = 0; i < N; ++i) _B[i] = B[i]; } inline void PolyLn(int *_A,int *_B) { static int tA[MS],tB[MS]; for (int i = 1; i < N; ++i) tA[i - 1] = (LL)_A[i] * i % Mod; PolyInv(_A,N - 1,tB); InitFNTT(N + N - 3); for (int i = N - 1; i < Sz; ++i) tA[i] = 0; for (int i = N - 1; i < Sz; ++i) tB[i] = 0; FNTT(tA,1); for (int i = 0; i < Sz; ++i) tA[i] = (LL)tA[i] * tB[i] % Mod; FNTT(tA,-1); _B[0] = 0; for (int i = 1; i < N; ++i) _B[i] = (LL)tA[i - 1] * Inv[i] % Mod; } inline void PolyExp(int *_A,B = getB(N); i < 1 << B; ++i) A[i] = 0; B[0] = 1; for (int L = 1; L < N; L <<= 1) { int L2 = L << 1,L4 = L << 2; for (int i = L; i < L2; ++i) B[i] = 0; PolyLn(B,L2,tA); InitFNTT(L4); for (int i = 0; i < L2; ++i) tA[i] = (!i + A[i] - tA[i] + Mod) % Mod; for (int i = L2; i < Sz; ++i) tA[i] = 0; for (int i = 0; i < L; ++i) tB[i] = B[i]; for (int i = L; i < Sz; ++i) tB[i] = 0; FNTT(tA,1); for (int i = 0; i < Sz; ++i) tA[i] = (LL)tA[i] * tB[i] % Mod; FNTT(tA,-1); for (int i = 0; i < L2; ++i) B[i] = tA[i]; } for (int i = 0; i < N; ++i) _B[i] = B[i]; } int M,N; int Ans[MS],Tmp[MS]; int main() { scanf("%d%d",&M,&N),--M; Init(M + 2); for (int i = 0; i <= M; ++i) Ans[i] = i & 1 ? Mod - 1 : 1; while (N--) { int a,b; scanf("%d%d",&a,&b); Tmp[0] = 1; int coef = (LL)(b + 1) * gInv(b) % Mod; for (int i = 1; i <= M; ++i) { coef = (LL)coef * (b - i + 1) % Mod * Inv[i + 1] % Mod; Tmp[i] = coef; } PolyLn(Tmp,M + 1,Tmp); for (int i = 0; i <= M; ++i) Tmp[i] = (LL)Tmp[i] * a % Mod; PolyExp(Tmp,Tmp); int qwq = qPow(b,a); for (int i = 0; i <= M; ++i) Tmp[i] = (LL)Tmp[i] * qwq % Mod; PolyConv(Ans,Tmp,Ans); } int tAns = Ans[M]; printf("%dn",tAns); return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |