C-Cells_2021牛客暑期多校训练营9

先放一个LGV引理的链接在这里。

主要讲讲题解中这里的推导

每次从后往前,后一列减去\(t\)倍前一列可得

\[(a_i+1)\prod_{k=2}^{j+1}{(a_i+k)}-t(a_i+1)\prod_{k=2}^{j}{(a_i+k)}=(a_i+1)(a_i+j+1-t)\prod_{k=2}^j{(a_i+k)}
\]

\(t=j\),可得

\[(a_i+1)^2\prod_{k=2}^j{(a_i+k)}
\]

重复这个过程,直到连乘的项消去,剩余第\(j\)列就是\((a_i+1)^j\)

这个是范德蒙矩阵的形式,具体化简过程百度或自己推。

最后要求\(\prod_{1\le i < j \le n}{(a_j-a_i)}\)​​,直接卷积求出所有差值的个数然后快速幂即可。由于相同差值至多出现1e5次,可以直接ntt。注意多项式乘法最后度数要乘2,这样卷积出来的结果才是正确的。

  1. #include <bits/stdc++.h>
  2. #define endl \'\n\'
  3. #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
  4. #define mp make_pair
  5. #define seteps(N) fixed << setprecision(N)
  6. typedef long long ll;
  7. using namespace std;
  8. /*-----------------------------------------------------------------*/
  9. ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
  10. #define INF 0x3f3f3f3f
  11. const int N = 3e6;
  12. const int M = 998244353;
  13. const double eps = 1e-5;
  14. int rev[N];
  15. inline ll qpow(ll a, ll b, ll m) {
  16. ll res = 1;
  17. while(b) {
  18. if(b & 1) res = (res * a) % m;
  19. a = (a * a) % m;
  20. b = b >> 1;
  21. }
  22. return res;
  23. }
  24. void change(ll y[], int len) {
  25. for(int i = 0; i < len; ++i) {
  26. rev[i] = rev[i >> 1] >> 1;
  27. if(i & 1) {
  28. rev[i] |= len >> 1;
  29. }
  30. }
  31. for(int i = 0; i < len; ++i) {
  32. if(i < rev[i]) {
  33. swap(y[i], y[rev[i]]);
  34. }
  35. }
  36. return;
  37. }
  38. void fft(ll y[], int len, int on) {
  39. change(y, len);
  40. for(int h = 2; h <= len; h <<= 1) {
  41. ll gn = qpow(3, (M - 1) / h, M);
  42. if(on == -1) gn = qpow(gn, M - 2, M);
  43. for(int j = 0; j < len; j += h) {
  44. ll g = 1;
  45. for(int k = j; k < j + h / 2; k++) {
  46. ll u = y[k];
  47. ll t = g * y[k + h / 2] % M;
  48. y[k] = (u + t) % M;
  49. y[k + h / 2] = (u - t + M) % M;
  50. g = g * gn % M;
  51. }
  52. }
  53. }
  54. if(on == -1) {
  55. ll inv = qpow(len, M - 2, M);
  56. for(int i = 0; i < len; i++) {
  57. y[i] = y[i] * inv % M;
  58. }
  59. }
  60. }
  61. int get(int x) {
  62. int res = 1;
  63. while(res < x) {
  64. res <<= 1;
  65. }
  66. return res;
  67. }
  68. ll f1[N], f2[N];
  69. int main() {
  70. IOS;
  71. int n;
  72. cin >> n;
  73. int mx = 1000000;
  74. int up = 0;
  75. ll rj = 1, prod = 1, tj = 1;
  76. for(int i = 1; i <= n; i++) {
  77. int x;
  78. cin >> x;
  79. f1[x] = 1;
  80. f2[mx - x] = 1;
  81. prod = prod * (x + 1) % M;
  82. tj = tj * i % M;
  83. rj = rj * tj % M;
  84. up = x;
  85. }
  86. rj = qpow(rj, M - 2, M);
  87. int len = get(2 * mx + 1);
  88. fft(f1, len, 1);
  89. fft(f2, len, 1);
  90. for(int i = 0; i < len; i++) f1[i] = f1[i] * f2[i] % M;
  91. fft(f1, len, -1);
  92. ll ans = 1;
  93. for(int i = 1; i <= mx; i++) {
  94. ans = ans * qpow(i, f1[mx - i], M) % M;
  95. }
  96. ans = ans * rj % M * prod % M;
  97. cout << ans << endl;
  98. }

版权声明:本文为limil原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/limil/p/15144595.html