前言

情人节写的这道题,题目名称好符合我当时的心情。


题目链接

Luogu:P4921

解法

容斥

我们发现最后要求的结果是恰好 \(k\) 对情侣坐在一起的方案数,我们就不难想到去计算恰好 \(n-k\) 对没坐在一起的方案数。那么我们很自然的得到最后答案: \(ans = C_n^k \times A_n^k \times 2^k \times g_{n-k}\),\(g_k\) 为恰好 \(k\) 对情侣没坐在一起的方案数,然后就可以快乐的容斥了:

\[g_k = \sum_{i=0}^k (-1)^i \times 2^i \times C_k^i \times A_k^i \times (2\times k -2\times i)!
\]

这玩意预处理一下也就是 \(O(n^2)\) 的复杂度,总复杂度也就是 \(O(Tn + N^2)\)。

反演

我们发现题目中有恰好 二字,这不就在暗示我们可以用二项式反演吗。我们直接令 \(F_i\) 为至少 \(i\) 对情侣坐一起的方案数,\(G_i\) 为恰好 \(i\) 对情侣坐一起的方案数,由二项式反演可知:

\[F_k = \sum_{i=k}^n \binom{i}{k} G_i \iff G_k = \sum_{i=k}^n (-1)^{i-k} \binom{i}{k} F_i
\]

我们现在只需要求出 \(F_i\) 即可。

显而易见,\(F_k = C_n^k \times A_n^k \times 2^k \times (2\times n - 2\times k)!\),我们将它代入到上面的式子得:

\[\begin{aligned}
G_k &= \sum_{i=k}^n (-1)^{i-k} \times 2^i \times C_i^k \times C_n^i \times A_n^i \times (2\times n - 2 \times i)! \\&
= \sum_{i=0}^{n-k} (-1)^i \times 2^{i+k} \times C_{i+k}^k \times C_n^{i+k} \times A_n^{i+k} \times (2\times n - 2 \times k - 2\times i)! \\&
= \frac{2^k \times n! \times n!}{k!} \sum_{i=0}^{n-k} \frac{(-1)^i \times 2^i \times (2\times n- 2\times k-2\times i)!}{i! \times (n - k - i)! \times (n - k - i)!}
\end{aligned}\]

我们也只需要进行预处理就可以了,最后复杂度和上边是一样的。

Code
#include<bits/stdc++.h>
#define int long long
const int M = 2e3 + 7 , mod = 998244353;
int fac[M] , inv[M] , f[M] , pow2[M];
inline int Pow(int a , int b) {
int ans = 1; for(;b; b >>= 1 , a= a * a % mod) if(b & 1) ans = ans * a % mod;
return ans;
}
inline int C(int n , int m) {
if(n < 0 || m < 0 || n < m) return 0;
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
inline int A(int n , int m) {
if(n < 0 || m < 0 || n < m) return 0;
return fac[n] * inv[n - m] % mod;
}
signed main () {
int t; std::cin >> t;
pow2[0] = 1, inv[0] = fac[0] = 1; for(int i = 1; i <= 2e3; ++ i) fac[i] = fac[i - 1] * i % mod , inv[i] = Pow(fac[i] , mod - 2) , pow2[i] = pow2[i - 1] * 2 % mod;
for(int i = 0; i <= 1e3; ++ i)
for(int j = 0; j <= i; ++ j) (f[i] += ((j & 1) ? mod - 1 : 1) * inv[j] % mod * pow2[j] % mod * fac[i - j << 1] % mod * inv[i - j] % mod * inv[i - j] % mod) %= mod;
while(t --) {
int n; std::cin >> n;
for(int i = 0; i <= n; ++ i) std::cout << (fac[n] * fac[n] % mod * pow2[i] % mod * inv[i] % mod * f[n - i] % mod) << '\n';
}
}

最新文章

  1. Excel—TEXT函数功能详解
  2. 转:工具类之SpannableStringUtils(相信你会爱上它)
  3. 如何用js定义数组,用js来拼接json字段
  4. 四则运算(Android)版
  5. python遍历数据
  6. VC编程技巧:IE控件的高级用法
  7. servlet 默认是线程安全的吗?
  8. 利用青瓷布局自定义加载的场景,而不是自己改写qici-loading
  9. 第四章SignalR自托管主机
  10. sqlite3结合ios开发
  11. 程序员高效Windows环境配置
  12. iOS-----------计算两个时间的时间差
  13. 大量Python开源第三方库资源分类整理,含菜鸟教程章节级别链接
  14. Delphi7使用一段时间后抽风提示注册
  15. 【python】变量的赋值、深浅拷贝
  16. 修改tomcat的server.xml配置web项目
  17. TWebBrowser禁止弹出Alert对话框
  18. 9.14 h5日记
  19. A总结
  20. 关于Entity Framework关系配置,提示列名XXXX_Id无效的问题

热门文章

  1. (未完成)JAVAWEB学习——
  2. 安装kubernetes dashboard以及用户授权
  3. ider git Reset Type 使用记录
  4. 本地开发环境使用redis
  5. docker compose设置不同容器间通信
  6. EXCEL函数总结
  7. 可汗儿童版kids安卓版下载安装教程
  8. Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M5:test (default-test) on project
  9. Github的.gitignore忽略文件
  10. ABAP 删除内表重复数据