题解

我,理解题解,用了一天

我,卡常数,又用了一天

到了最后,我才发现,我有个加法取模,写的是while(c >= MOD) c -= MOD

我把while改成if,时间,少了

六倍。

六倍。

六倍!!!!

maya我又用第一次T的代码改掉了while,我第一次T的代码也A了= =

那我,改单位复根,FFT循环展开,分治内部循环展开,为了啥= =

好吧,但是我最后上榜了。。。LOJ第四的样子。。

\(\prod_{i = 1}^{N} d_{i}^{m}\sum_{i = 1}^{N}d_{i}^{m}\)

这个时候,我们把连通块当成一个大点做prufer序,序列里的每个连通块\(i\)的位置都有\(a_{i}\)种填数方式,式子可以改写成这样

\(\prod_{i = 1}^{N} a_{i}^{d_{i}}d_{i}^{m}\sum_{i = 1}^{N}d_{i}^{m}\)

\(\sum_{i = 1}^{N} d_{i}^{m}\prod_{j = 1}^{N}a_{j}^{d_{j}}d_{j}^{m}\)

我们考虑一下一个最暴力的dp(我的第一反应,啥,这怎么是dp?

当然是dp出一个prufer序列啦

\(f[i][j]\)表示考虑了前i个数,填了j个格子,没有多乘任何一个\(d_{i}^{m}\)

\(g[i][j]\)表示考虑了前i个数,填了j个格子,已经乘了一个\(d_{i}^{m}\)

转移的时候,枚举当前这个数填上k个格子

\(f[i][j] += f[i - 1][j - k] * a_{i}^{k} k^{m}\)

\(g[i][j] += g[i - 1][j - k] * a_{i}^{k} k^{m}\)

\(g[i][j] += f[i - 1][j - k] * a_{i}^{k} k^{2m}\)

复杂度\(O(n^{3})\)

但是显然过不掉

我们再考虑一个……套路!因为m出奇的小?

乘方转斯特林数

想一下\(x^{m}\)的组合意义,相当于\(m\)种颜色涂在\(x\)个格子里,每个种颜色只能涂一个格子,但是每个格子可以涂很多颜色

再看一下原式子,把它变成这样的形式

\(\sum_{i = 1}^{N} a_{i}^{d_{i}}d_{i}^{2m}\prod_{j = 1,j != i}^{N}a_{j}^{d_{j}}d_{j}^{m}\)

然后,我们把乘方拆开,怎么拆呢

考虑到上述的组合意义

我们也就是求所有prufer序列的染色方式,在每一次决策的时候选择是否将某个点用\(2m\)种颜色染,我们在序列后面(脑补)出1 - N,这样prufer序列里数字出现的个数就正好是点度

\(m\)很小,染色的格子很少,我们从这个方向考虑

设已经被染色的格子个数是\(j\),那么再放入一个新的数,染色个数为\(k\)的时候,需要乘上

\(\binom{n - 2 - j}{k}((S(m,k)k! + S(m,k + 1)(k + 1)!)\)

我们就是在\(n - 2 - j\)个没有染色的位置里,选择\(k\)个位置,然后\(S(m,k)\)就相当于把这\(m\)种颜色分配到这\(k\)个位置里,然后这些颜色还可以再次打乱顺序进行排列,就再乘一个\(k!\)

为什么还有\(k + 1\),因为\(k\)代表的是这\(n - 2\)个prufer序里面的这类点染色的个数,我们还有后面脑补出的1 - N的位置,所以要讨论+1的情况

这个时候我们已经给每个连通块选好了\(d_{i}\)个点,并涂好了颜色,然后我们再乘上式子里的\(a_{i}^{d_{i}}\)就好

如果是\(2m\)种颜色染色,把\(m\)换成\(2m\)就可以

我们观察一下这个组合数,我们会发现我们可以把\(\frac{1}{k!}\)分离出来,每次统计贡献的时候加上,剩下的等全部算完答案后,如果染色的个数为\(j\),那么答案再乘上\(\frac{(n - 2)!}{(n - 2 - j)!}\)

同时,我们除了染色的位置还有很多空位,每个空位都有\(\sum_{i = 1}^{n}a_{i}\)种情况,如果有\(j\)个位置被染色了,那么答案还要再乘上

\((\sum_{i = 1}^{n}a_{i})^{n - 2 - j}\)

这样的复杂度是\(n^2m\)的

什么,你觉得想到这个有点别扭?

那我写一个更套路一点的想法吧

我们回忆到斯特林数的展开式,根据容斥,显然有

\(S(m,k) = \frac{1}{k!} \sum_{i = 0}^{k}(-1)^{i} \binom{k}{i} (k - i)^{m}\)

什么,你说你不知道这个式子……简单理解一下,就是我们枚举\(i\)个盒子里没有任何元素,\(\binom{k}{i}\)枚举了所有\(i\)个盒子的集合……就有了这个容斥

我们稍稍的变一下形

\(S(m,k) k!= \sum_{i = 0}^{k}(-1)^{k - i} \binom{k}{i} (i)^{m}\)

有没有注意到啥。。这个式子无比的眼熟

如果还没注意到就设

\(f(k) = S(m,k) k!\)

\(g(k) = k^{m}\)

\(f(k) = \sum_{i = 0}^{k}(-1)^{k - i} \binom{k}{i} g(i)\)

如果你还不为所动……我就打人了= =

好吧,这很明显是个二项式反演,我们尝试用\(f(x)\)表示\(g(x)\)

\(g(x) = \sum_{i = 0}^{x}\binom{x}{i}f(i)\)

我们尝试把点度\(d\)代入

\(d^{m} = \sum_{k = 0}^{d} \binom{d}{k} S(m,k) k!\)

\(d\)可能很大,是没错,但是\(m\)很小,在这里,我们假设\(m < d\),因为对于\(S(m,k)\)如果\(k > m\)那么\(S(m,k) = 0\)

\(d^{m} = \sum_{k = 0}^{m} \binom{d}{k} S(m,k) k!\)

那么这个方程是什么呢,代表了\(d^{m}\)可以用在\(d\)位置里选\(k\)个位置然后乘上\(S(m,k)k!\)来组合出来

嗯?和\(O(n^3)\)的算法有点类似了?

但是和那个暴力DP不同的是,我们只需要枚举\(m\)个位置了,复杂度降到了\(O(n^{2}m)\)

我们只需要考虑如何用dp覆盖对于每一种prufer序列我们对每个连通块的大点,每种点都选\(0 - m\)个位置,来乘上\(S(m,k)k!\)

这个时候,我们想到我们记录染色的位置,来求出所有本质不同的染色序列,这就是我们的答案了

会不会有人到这里就不理解\(S(m,k + 1)(k + 1)!\)了啊……,因为prufer序就是前面n - 2个数决定的,不关后面(脑补)的1 - N个数的顺序

所以我们要单独讨论一下,可以认为是我们对于这个式子

\(d^{m} = \sum_{k = 0}^{m} \binom{d}{k} S(m,k) k!\)

假如现在k = 0,我们的\(S(m,k + 1)(k + 1)!\)是统计了k = 1时的某些情况

假如现在k = 1,我们的\(S(m,k + 1)(k + 1)!\)是统计了k = 2时的某些情况

\(f,g\)的定义和前面的暴力dp定义类似

\(f[i][j]\)表示考虑了前\(i\)个点,有\(j\)个位置被染色了

\(g[i][j]\)表示考虑了前\(i\)个点,有\(j\)个位置被染色,还同时统计了某一处位置用\(2m\)染色了

给出一段暴力的代码吧……

  1. int cur = 0;
  2. f[0][0] = 1;
  3. for(int i = 1 ; i <= N ; ++i) {
  4. memset(f[cur ^ 1],0,sizeof(f[cur ^ 1]));
  5. memset(g[cur ^ 1],0,sizeof(g[cur ^ 1]));
  6. for(int j = 0 ; j <= N - 2 ; ++j) {
  7. for(int k = 0 ; k <= M && j + k <= N - 2 ; ++k) {
  8. update(f[cur ^ 1][j + k],mul(f[cur][j],F1[i][k]));
  9. update(g[cur ^ 1][j + k],mul(g[cur][j],F1[i][k]));
  10. }
  11. for(int k = 0 ; k <= 2 * M && j + k <= N - 2; ++k) {
  12. update(g[cur ^ 1][j + k],mul(f[cur][j],F2[i][k]));
  13. }
  14. }
  15. cur ^= 1;
  16. }

\(F1,F2\)分别代表是用一个\(m\)染色还是用2个\(m\)染色

似乎没有什么可优化啦……

然而这个方程本质是个卷积,可以上分治FFT,然后就在\(O(nm \log n)\)解决了。。。

他说不卡常……确实不卡常,我的错误神奇得太离谱了= =

正常模样的代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <cstring>
  7. #include <map>
  8. //#define ivorysi
  9. #define pb push_back
  10. #define space putchar(' ')
  11. #define enter putchar('\n')
  12. #define mp make_pair
  13. #define pb push_back
  14. #define fi first
  15. #define se second
  16. #define mo 974711
  17. #define MAXN 30005
  18. using namespace std;
  19. typedef long long int64;
  20. typedef double db;
  21. template<class T>
  22. void read(T &res) {
  23. res = 0;char c = getchar();T f = 1;
  24. while(c < '0' || c > '9') {
  25. if(c == '-') f = -1;
  26. c = getchar();
  27. }
  28. while(c >= '0' && c <= '9') {
  29. res = res * 10 + c - '0';
  30. c = getchar();
  31. }
  32. res *= f;
  33. }
  34. template<class T>
  35. void out(T x) {
  36. if(x < 0) {putchar('-');x = -x;}
  37. if(x >= 10) {
  38. out(x / 10);
  39. }
  40. putchar('0' + x % 10);
  41. }
  42. const int MOD = 998244353,G = 3,L = (1 << 20);
  43. int fac[MAXN],S[75][75],invfac[MAXN],N,M,a[MAXN],P[MAXN][75],F1[MAXN][75],F2[MAXN][75];
  44. int f[2][MAXN],g[2][MAXN],W[L + 5];
  45. int mul(int a,int b) {return 1LL * a * b % MOD;}
  46. int inc(int a,int b) {a = a + b;if(a >= MOD) a -= MOD;return a;}
  47. void update(int &x,int y) {x = inc(x,y);}
  48. int fpow(int x,int c) {
  49. int res = 1,t = x;
  50. while(c) {
  51. if(c & 1) res = mul(res,t);
  52. t = mul(t,t);
  53. c >>= 1;
  54. }
  55. return res;
  56. }
  57. struct poly {
  58. vector<int> a;
  59. poly() {a.clear();}
  60. friend void NTT(poly &f,int T,int on) {
  61. f.a.resize(T);
  62. for(int i = 1 , j = T / 2; i < T - 1; ++i) {
  63. if(i < j) swap(f.a[i],f.a[j]);
  64. int k = T / 2;
  65. while(j >= k) {j -= k;k >>= 1;}
  66. j += k;
  67. }
  68. for(int h = 2 ; h <= T ; h <<= 1) {
  69. int wn = W[(L + on * L / h) % L];
  70. for(int k = 0 ; k < T ; k += h) {
  71. int w = 1;
  72. for(int j = k ; j < k + h / 2 ; ++j) {
  73. int u = f.a[j],t = mul(f.a[j + h / 2],w);
  74. f.a[j] = inc(u,t);
  75. f.a[j + h / 2] = inc(u,MOD - t);
  76. w = mul(w,wn);
  77. }
  78. }
  79. }
  80. if(on == -1) {
  81. int InvT = fpow(T,MOD - 2);
  82. for(int i = 0 ; i < T ; ++i) f.a[i] = mul(f.a[i],InvT);
  83. }
  84. }
  85. friend poly operator + (const poly &f,const poly &g) {
  86. int T = max(f.a.size(),g.a.size());
  87. poly h;h.a.resize(T);
  88. for(int i = 0 ; i < T ; ++i) h.a[i] = inc(f.a[i],g.a[i]);
  89. return h;
  90. }
  91. friend poly operator * (poly f,poly g) {
  92. int T = 1,t = f.a.size() + g.a.size();
  93. while(T <= t) T <<= 1;
  94. NTT(f,T,1);NTT(g,T,1);
  95. poly h;h.a.resize(T);
  96. for(int i = 0 ; i < T ; ++i) h.a[i] = mul(f.a[i],g.a[i]);
  97. NTT(h,T,-1);
  98. for(int i = T - 1 ; i >= 0 ; --i) {
  99. if(!h.a[i]) h.a.pop_back();
  100. else break;
  101. }
  102. if(h.a.size() > N - 1) h.a.resize(N - 1);
  103. return h;
  104. }
  105. };
  106. void Init() {
  107. read(N);read(M);
  108. int T = max(N,2 * M + 1);
  109. fac[0] = 1;
  110. for(int i = 1 ; i <= T ; ++i) fac[i] = mul(fac[i - 1],i);
  111. invfac[T] = fpow(fac[T],MOD - 2);
  112. for(int i = T - 1; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
  113. S[0][0] = 1;
  114. for(int i = 1 ; i <= 70 ; ++i) {
  115. for(int j = 1 ; j <= i ; ++j) {
  116. S[i][j] = inc(S[i - 1][j - 1],mul(S[i - 1][j],j));
  117. }
  118. }
  119. for(int i = 1 ; i <= N ; ++i) read(a[i]);
  120. for(int i = 1 ; i <= N ; ++i) {
  121. P[i][0] = 1;
  122. for(int j = 1 ; j <= 70 ; ++j) {
  123. P[i][j] = mul(P[i][j - 1],a[i]);
  124. }
  125. }
  126. W[0] = 1,W[1] = fpow(G,(MOD - 1) / L);
  127. for(int i = 2 ; i < L ; ++i) W[i] = mul(W[i - 1],W[1]);
  128. }
  129. pair<poly,poly> Solve(int L,int R) {
  130. if(L == R) {
  131. poly s,t;s.a.resize(M + 1);t.a.resize(2 * M + 1);
  132. for(int i = 0 ; i <= 2 * M ; ++i) {
  133. if(i <= M)
  134. s.a[i] = mul(mul(inc(mul(S[M][i],fac[i]),mul(S[M][i + 1],fac[i + 1])),invfac[i]),P[L][i]);
  135. t.a[i] = mul(mul(inc(mul(S[2 * M][i],fac[i]),mul(S[2 * M][i + 1],fac[i + 1])),invfac[i]),P[L][i]);
  136. }
  137. return mp(s,t);
  138. }
  139. int mid = (L + R) >> 1;
  140. pair<poly,poly> S = Solve(L,mid),T = Solve(mid + 1,R);
  141. return mp(S.fi * T.fi,S.se * T.fi + S.fi * T.se);
  142. }
  143. int main() {
  144. #ifdef ivorysi
  145. freopen("f1.in","r",stdin);
  146. #endif
  147. Init();
  148. pair<poly,poly> res = Solve(1,N);
  149. poly g = res.se;g.a.resize(N - 1);
  150. int sum = 0,p = 1,ans = 0,t = 1;
  151. for(int i = 1 ; i <= N ; ++i) sum = inc(sum,a[i]),p = mul(p,a[i]);
  152. for(int i = N - 2 ; i >= 0; --i) {
  153. ans = inc(ans,mul(mul(g.a[i],t),invfac[N - 2 - i]));
  154. t = mul(t,sum);
  155. }
  156. ans = mul(ans,mul(fac[N - 2],p));
  157. out(ans);putchar('\n');
  158. return 0;
  159. }

卡常之后的代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <cstring>
  7. #include <map>
  8. //#define ivorysi
  9. #define pb push_back
  10. #define space putchar(' ')
  11. #define enter putchar('\n')
  12. #define mp make_pair
  13. #define pb push_back
  14. #define fi first
  15. #define se second
  16. #define mo 974711
  17. #define MAXN 400005
  18. #define RG register
  19. using namespace std;
  20. typedef long long int64;
  21. typedef double db;
  22. template<class T>
  23. void read(T &res) {
  24. res = 0;char c = getchar();T f = 1;
  25. while(c < '0' || c > '9') {
  26. if(c == '-') f = -1;
  27. c = getchar();
  28. }
  29. while(c >= '0' && c <= '9') {
  30. res = res * 10 + c - '0';
  31. c = getchar();
  32. }
  33. res *= f;
  34. }
  35. template<class T>
  36. void out(T x) {
  37. if(x < 0) {putchar('-');x = -x;}
  38. if(x >= 10) {
  39. out(x / 10);
  40. }
  41. putchar('0' + x % 10);
  42. }
  43. const int MOD = 998244353,L = (1 << 16);
  44. int fac[MAXN],S[105][105],invfac[MAXN],a[MAXN],N,M,P[MAXN][105];
  45. int W[L + 5],IW[L + 5],top,fl[MAXN],fr[MAXN],gl[MAXN],gr[MAXN],f[MAXN],g[MAXN];
  46. vector<int> F[105],G[105];
  47. inline int mul(RG const int &a,RG const int &b) {return (int64)a * b % MOD;}
  48. inline int inc(RG const int &a,RG const int &b) {RG int c = a + b;if(c >= MOD) c -= MOD;return c;}
  49. int fpow(RG int x,RG int c) {
  50. RG int res = 1,t = x;
  51. while(c) {
  52. if(c & 1) res = mul(res,t);
  53. t = mul(t,t);
  54. c >>= 1;
  55. }
  56. return res;
  57. }
  58. void NTT(RG int *f,RG int T,RG int on,RG int *w) {
  59. RG int tmp,*wm,*ai,*ami;
  60. for(RG int i = 1 , j = T / 2; i < T - 1 ; ++i) {
  61. if(i < j) {tmp = f[i];f[i] = f[j];f[j] = tmp;}
  62. RG int k = T / 2;
  63. while(j >= k) {
  64. j -= k;
  65. k >>= 1;
  66. }
  67. j += k;
  68. }
  69. #define work(j) {tmp = mul(ami[j],wm[j]);ami[j] = inc(ai[j],MOD - tmp);ai[j] = inc(ai[j],tmp); }
  70. for(RG int h = 2,m = 1; h <= T ; m = h,h <<= 1) {
  71. wm = w + m;
  72. if(m < 8) {
  73. for(RG int i = 0 ; i < T ; i += h) {
  74. ai = f + i,ami = f + m + i;
  75. for(RG int j = 0 ; j < m ; ++j) work(j);
  76. }
  77. }
  78. else {
  79. for(RG int i = 0 ; i < T ; i += h) {
  80. ai = f + i,ami = f + m + i;
  81. for(RG int j = 0 ; j < m ; j += 8) {
  82. work(j);
  83. work(j + 1);
  84. work(j + 2);
  85. work(j + 3);
  86. work(j + 4);
  87. work(j + 5);
  88. work(j + 6);
  89. work(j + 7);
  90. }
  91. }
  92. }
  93. }
  94. if(on < 0) {
  95. RG int InvT = fpow(T,MOD - 2);
  96. #define C(x,y) {f[x] = mul(f[x],y);}
  97. if(T < 8) {for(RG int i = 0 ; i < T ; ++i) C(i,InvT);}
  98. else {
  99. for(RG int i = 0 ; i < T ; i += 8) {
  100. C(i,InvT);
  101. C(i + 1,InvT);
  102. C(i + 2,InvT);
  103. C(i + 3,InvT);
  104. C(i + 4,InvT);
  105. C(i + 5,InvT);
  106. C(i + 6,InvT);
  107. C(i + 7,InvT);
  108. }
  109. }
  110. }
  111. }
  112. void Init() {
  113. read(N);read(M);
  114. RG int T = max(N,2 * M + 1);
  115. fac[0] = 1;
  116. for(RG int i = 1 ; i <= T ; ++i) fac[i] = mul(fac[i - 1],i);
  117. invfac[T] = fpow(fac[T],MOD - 2);
  118. for(RG int i = T - 1; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
  119. S[0][0] = 1;
  120. for(RG int i = 1 ; i <= 70 ; ++i) {
  121. for(RG int j = 1 ; j <= i ; ++j) {
  122. S[i][j] = inc(S[i - 1][j - 1],mul(S[i - 1][j],j));
  123. }
  124. }
  125. for(RG int j = 1 ; j <= 2 * M ; ++j) {
  126. S[M][j] = mul(S[M][j],fac[j]);
  127. S[2 * M][j] = mul(S[2 * M][j],fac[j]);
  128. }
  129. for(RG int j = 0 ; j <= 2 * M ; ++j) {
  130. S[M][j] = mul(inc(S[M][j],S[M][j + 1]),invfac[j]);
  131. S[2 * M][j] = mul(inc(S[2 * M][j],S[2 * M][j + 1]),invfac[j]);
  132. }
  133. for(RG int i = 1 ; i <= N ; ++i) read(a[i]);
  134. for(RG int i = 1 ; i <= N ; ++i) {
  135. P[i][0] = 1;
  136. for(RG int j = 1 ; j <= 70 ; ++j) {
  137. P[i][j] = mul(P[i][j - 1],a[i]);
  138. }
  139. }
  140. RG int half = L / 2;
  141. RG int t1 = fpow(3,(MOD - 1) / L),t2 = fpow(t1,MOD - 2);
  142. W[half] = 1;IW[half] = 1;
  143. for(RG int i = 1 ; i < half; ++i) W[i + half] = mul(W[i + half - 1],t1),IW[i + half] = mul(IW[i + half - 1],t2);
  144. for(RG int i = half - 1 ; i >= 0 ; --i) W[i] = W[i << 1],IW[i] = IW[i << 1];
  145. }
  146. void Solve(RG int L,RG int R) {
  147. if(L == R) {
  148. ++top;
  149. F[top].resize(M + 1);G[top].resize(2 * M + 1);
  150. for(RG int i = 0 ; i <= 2 * M ; ++i) {
  151. if(i <= M)
  152. F[top][i] = mul(S[M][i],P[L][i]);
  153. G[top][i] = mul(S[2 * M][i],P[L][i]);
  154. }
  155. return ;
  156. }
  157. RG int mid = (L + R) >> 1;
  158. Solve(L,mid);int Ld = top;
  159. Solve(mid + 1,R);int Rd = top;
  160. top -= 2;
  161. RG int s1 = F[Ld].size(),s2 = F[Rd].size(),s3 = G[Ld].size(),s4 = G[Rd].size();
  162. RG int t = max(max(s1 + s2,s1 + s4),s3 + s2);
  163. RG int K = 1;while(K <= t) K <<= 1;
  164. for(int i = 0 ; i < s1 ; ++i) fl[i] = F[Ld][i];
  165. for(int i = 0 ; i < s2 ; ++i) fr[i] = F[Rd][i];
  166. for(int i = 0 ; i < s3 ; ++i) gl[i] = G[Ld][i];
  167. for(int i = 0 ; i < s4 ; ++i) gr[i] = G[Rd][i];
  168. fill(fl + s1,fl + K,0);
  169. fill(fr + s2,fr + K,0);
  170. fill(gl + s3,gl + K,0);
  171. fill(gr + s4,gr + K,0);
  172. NTT(fl,K,1,W);NTT(fr,K,1,W);NTT(gl,K,1,W);NTT(gr,K,1,W);
  173. #define Calc1(i) {f[i] = mul(fl[i],fr[i]);}
  174. #define Calc2(i) {g[i] = inc(mul(fl[i],gr[i]),mul(gl[i],fr[i]));}
  175. if(K < 8) {
  176. for(int i = 0 ; i < K ; ++i) {
  177. Calc1(i);Calc2(i);
  178. }
  179. }
  180. else {
  181. for(RG int i = 0 ; i < K ; i += 8) {
  182. Calc1(i);Calc1(i + 1);
  183. Calc1(i + 2);Calc1(i + 3);
  184. Calc1(i + 4);Calc1(i + 5);
  185. Calc1(i + 6);Calc1(i + 7);
  186. Calc2(i);Calc2(i + 1);
  187. Calc2(i + 2);Calc2(i + 3);
  188. Calc2(i + 4);Calc2(i + 5);
  189. Calc2(i + 6);Calc2(i + 7);
  190. }
  191. }
  192. NTT(f,K,-1,IW);NTT(g,K,-1,IW);
  193. ++top;
  194. F[top].clear();G[top].clear();
  195. t = min(N - 2,K - 1);
  196. while(t >= 0) {
  197. if(!f[t]) --t;
  198. else break;
  199. }
  200. for(RG int i = 0 ; i <= t ; ++i) F[top].pb(f[i]);
  201. t = min(N - 2,K - 1);
  202. while(t >= 0) {
  203. if(!g[t]) --t;
  204. else break;
  205. }
  206. for(RG int i = 0 ; i <= t ; ++i) G[top].pb(g[i]);
  207. }
  208. int main() {
  209. #ifdef ivorysi
  210. freopen("f1.in","r",stdin);
  211. #endif
  212. Init();
  213. Solve(1,N);
  214. G[top].resize(N - 1);
  215. RG int ans = 0,sum = 0,p = 1,t = 1;
  216. for(RG int i = 1 ; i <= N ; ++i) sum = inc(sum,a[i]),p = mul(p,a[i]);
  217. for(RG int i = N - 2 ; i >= 0 ; --i) {
  218. ans = inc(ans,mul(mul(G[top][i],t),invfac[N - 2 - i]));
  219. t = mul(t,sum);
  220. }
  221. ans = mul(mul(ans,p),fac[N - 2]);
  222. out(ans);enter;
  223. //out(clock());enter;
  224. return 0;
  225. }

【LOJ】#2320. 「清华集训 2017」生成树计数的更多相关文章

  1. Loj 2320.「清华集训 2017」生成树计数

    Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...

  2. LOJ2320「清华集训 2017」生成树计数

    由于菜鸡的我实在是没学会上升幂下降幂那一套理论,这里用的是完全普通多项式的做法. 要是有大佬愿意给我讲讲上升幂下降幂那一套东西,不胜感激orz! 首先可以想到prufer序列,如果不会的话可以左转百度 ...

  3. Loj #2331. 「清华集训 2017」某位歌姬的故事

    Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...

  4. Loj #2324. 「清华集训 2017」小 Y 和二叉树

    Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...

  5. Loj #2321. 「清华集训 2017」无限之环

    Loj #2321. 「清华集训 2017」无限之环 曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏: 游戏在一个 \(n \times m\) 的网格状棋 ...

  6. [LOJ#2330]「清华集训 2017」榕树之心

    [LOJ#2330]「清华集训 2017」榕树之心 试题描述 深秋.冷风吹散了最后一丝夏日的暑气,也吹落了榕树脚下灌木丛的叶子.相识数年的Evan和Lyra再次回到了小时候见面的茂盛榕树之下.小溪依旧 ...

  7. [LOJ#2329]「清华集训 2017」我的生命已如风中残烛

    [LOJ#2329]「清华集训 2017」我的生命已如风中残烛 试题描述 九条可怜是一个贪玩的女孩子. 这天她在一堵墙钉了 \(n\) 个钉子,第 \(i\) 个钉子的坐标是 \((x_i,y_i)\ ...

  8. [LOJ#2328]「清华集训 2017」避难所

    [LOJ#2328]「清华集训 2017」避难所 试题描述 "B君啊,你当年的伙伴都不在北京了,为什么你还在北京呢?" "大概是因为出了一些事故吧,否则这道题就不叫避难所 ...

  9. [LOJ#2327]「清华集训 2017」福若格斯

    [LOJ#2327]「清华集训 2017」福若格斯 试题描述 小d是4xx9小游戏高手. 有一天,小d发现了一个很经典的小游戏:跳青蛙. 游戏在一个 \(5\) 个格子的棋盘上进行.在游戏的一开始,最 ...

随机推荐

  1. springboot 日期转化报错

    问题场景: 使用Springboot框架搭建服务,传日期参数json参数为2016-08-15 17:00:00这种格式,springboot中不能识别,将其转化为对象对应的日期属性.而是抛出异常信息 ...

  2. 2016/2/13 《计算机系统要素》(The Elements of Computing Systems)读书笔记(1)

    过年期间一直在啃一本书,学习计算机组成原理. 这是一本很棒的书,是一个基于项目的学习过程.可以让人理解的很深刻. coursera上有这本书前半部分的教程,是由书的作者团队们开的课,个人认为很棒,可惜 ...

  3. crontab定时任务_net

    2017年2月25日, 星期六 crontab定时任务 19. crontab 定时任务 通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell script脚本.时间间隔 ...

  4. Tomcat设置编码问题

    为了解决编码问题,在tomcat的server.xml文件中添加了useBodyEncodingForURI="true"配置,如下 <Connector port=&quo ...

  5. Jekins - Hello world,Jekins + Maven + Git + Tomcat 的简单应用

    Java Web 工程 新建一个简单的 Java Web 工程,并提交至 GitHub,可参考 Eclipse 提交工程至 GitHub 下载 jekins.war 在 http://mirrors. ...

  6. soj2013.Pay Back

    2013. Pay Back Constraints Time Limit: 1 secs, Memory Limit: 256 MB Description "Never a borrow ...

  7. git之存储(git stash)-------(二)

    关于git stash命令的使用方法网上一大把,我想记录的是我在使用过程中觉得实用及好用的: 当在一个分支的开发工作未完成,却又要切换到另外一个分支进行开发的时候,可以先将自己写好的代码,储存在一个箱 ...

  8. nodejs学习:net模块

    官方API文档地址:https://nodejs.org/api/net.html 创建一个server.js var net = require('net'); var PORT = 8099; v ...

  9. python基础===一行 Python 代码实现并行(转)

    原文:https://medium.com/building-things-on-the-internet/40e9b2b36148 译文:https://segmentfault.com/a/119 ...

  10. 移动端测试=== adb 无线连接手机

    无线连接(需要借助 USB 线) 除了可以通过 USB 连接设备与电脑来使用 adb,也可以通过无线连接——虽然连接过程中也有需要使用 USB 的步骤,但是连接成功之后你的设备就可以在一定范围内摆脱 ...