题意:求所有长度为\(n\)的排列\(p\)中,有多少个满足:对于所有\(i \,(1 \leq i \leq n)\),其中恰好有\(k\)个满足\(|p_i - i| = 1\)。答案对\(10^9 + 7\)取模。

\(n \leq 10^3\)

首先,让我们考虑这个类似反演的结论:

对于\(F(n)\)和\(f(n)\),则满足

\[F(n) = \sum_{k \geq n}{{k}\choose{n}}f(k) \iff f(n) = \sum_{k \geq n}(-1)^{k-n}{{k}\choose{n}}F(k)
\]

对于充分性,我们有

\[\begin{aligned} & \sum_{k \geq n}(-1)^{k-n}{{k}\choose{n}}F(k) \\
= & \sum_{k \geq n}(-1)^{k-n}{{k}\choose{n}} \sum_{j \geq k} {{j}\choose{k}} f(j) \\
= & \sum_{j \geq n} f(j) {{j}\choose{n}} \sum_{n \leq k \leq j} (-1)^{k-n} {{j-n}\choose{k-n}} \\
= & \sum_{j \geq n} f(j) {{j}\choose{n}} \sum_{0 \leq k \leq j-n} (-1)^k {{j-n}\choose{k}} \\
= & \sum_{j \geq n} f(j) {{j}\choose{n}} (1-1)^{j-n} \\
= & f(n)\end{aligned}
\]

而对于必要性,我们也能给出类似的证明。

观察这个结论,不难发现,我们平时使用的容斥就是这个结论求\(f(0)\)时的特殊情况。而现在我们要求的是\(f(k)\),问题就变成了把所有\(F(n)\)都求出来。

\(F(n)\)的定义正对应了我们求至少有\(k\)个的情况总数时,重复统计所得到的结果。这使得它可以比较容易地求出。

我们考虑权值和位置表示为二分图的形式,那么问题就在于求二分图恰好有\(k\)个匹配的方案数。考虑dp。设dp[i,j,a,b]表示当前匹配到第\(i\)个权值和位置,已经有\(j\)个匹配,并且\(a\)和\(b\)分别表示第\(i\)个位置与权值是否已经与编号更小的权值与位置匹配。通过枚举\(a\)和\(b\),很容易能得到dp的转移。当然,最后的答案还要乘以一个阶乘。

时间复杂度\(O(n^2)\)。

#include <bits/stdc++.h>
using namespace std;
const int N = 1010, MOD = 1000000007;
typedef long long ll;
ll power(ll a,int b) {
ll res = 1;
while (b) {
if (b&1) res = 1ll * res * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return res;
}
int n,k;
ll dp[N][N][2][2],jc[N],inv[N],ans;
ll comb(int a,int b) {
if (a < 0 || b < 0 || a < b)
return 0;
return jc[a] * inv[b] % MOD * inv[a-b] % MOD;
}
int main() {
scanf("%d%d",&n,&k);
dp[0][0][1][1] = 1;
for (int i = 1 ; i <= n ; ++ i)
for (int j = 0 ; j <= n ; ++ j) {
(dp[i][j][0][0] = dp[i-1][j][0][0] + dp[i-1][j][1][0] + dp[i-1][j][0][1] + dp[i-1][j][1][1]) %= MOD;
if (j >= 1) {
(dp[i][j][1][0] = dp[i-1][j-1][0][0] + dp[i-1][j-1][1][0]) %= MOD;
(dp[i][j][0][1] = dp[i-1][j-1][0][0] + dp[i-1][j-1][0][1]) %= MOD;
}
if (j >= 2)
dp[i][j][1][1] = dp[i-1][j-2][0][0];
}
jc[0] = 1;
for (int i = 1 ; i <= n ; ++ i)
jc[i] = 1ll * i * jc[i-1] % MOD;
inv[n] = power(jc[n],MOD-2);
for (int i = n-1 ; i >= 0 ; -- i)
inv[i] = 1ll * inv[i+1] * (i+1) % MOD;
for (int j = k, p = 1 ; j <= n ; ++ j, p = -p) {
ll v = 1ll * jc[n-j] * (dp[n][j][0][0] + dp[n][j][1][0] + dp[n][j][0][1] + dp[n][j][1][1]) % MOD;
(ans += p * comb(j,k) * v % MOD) %= MOD;
}
ans = (ans % MOD + MOD) % MOD;
cout << ans << endl;
return 0;
}

小结:这种类似于反演的东西是很多组合问题的通用方法,希望自己能实现灵活的运用。

【做题】CF285E. Positions in Permutations——dp+容斥的更多相关文章

  1. CF285E Positions in Permutations(dp+容斥)

    题意,给定n,k,求有多少排列是的 | p[i]-i |=1 的数量为k. Solution 直接dp会有很大的后效性. 所以我们考虑固定k个数字使得它们是合法的,所以我们设dp[i][j][0/1] ...

  2. 【CF715E】Complete the Permutations(容斥,第一类斯特林数)

    [CF715E]Complete the Permutations(容斥,第一类斯特林数) 题面 CF 洛谷 给定两个排列\(p,q\),但是其中有些位置未知,用\(0\)表示. 现在让你补全两个排列 ...

  3. [Luogu P1450] [HAOI2008]硬币购物 背包DP+容斥

    题面 传送门:https://www.luogu.org/problemnew/show/P1450 Solution 这是一道很有意思的在背包里面做容斥的题目. 首先,我们可以很轻松地想到暴力做背包 ...

  4. bzoj 3622 DP + 容斥

    LINK 题意:给出n,k,有a,b两种值,a和b间互相配对,求$a>b$的配对组数-b>a的配对组数恰好等于k的情况有多少种. 思路:粗看会想这是道容斥组合题,但关键在于如何得到每个a[ ...

  5. 【BZOJ 4665】 4665: 小w的喜糖 (DP+容斥)

    4665: 小w的喜糖 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 94  Solved: 53 Description 废话不多说,反正小w要发喜 ...

  6. CodeForces - 285E: Positions in Permutations(DP+组合数+容斥)

    Permutation p is an ordered set of integers p1,  p2,  ...,  pn, consisting of n distinct positive in ...

  7. CDOJ 1294 天行廖的游戏 dp 容斥

    天行廖的游戏 题目连接: http://acm.uestc.edu.cn/#/problem/show/1294 Description 天行健,君子以自强不息.地势坤,廖爷以厚德载物 一日在喵哈哈村 ...

  8. codeforces 342D Xenia and Dominoes(状压dp+容斥)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud D. Xenia and Dominoes Xenia likes puzzles ...

  9. BZOJ.4559.[JLOI2016]成绩比较(DP/容斥 拉格朗日插值)

    BZOJ 洛谷 为什么已经9点了...我写了多久... 求方案数,考虑DP... \(f[i][j]\)表示到第\(i\)门课,还有\(j\)人会被碾压的方案数. 那么\[f[i][j]=\sum_{ ...

随机推荐

  1. Rpgmakermv(34) Mog_Event Sensor

    原文: =============================================================================+++ MOG - Event Sen ...

  2. JTable的模型

    2018-11-04 23:15:21开始写 模型类 import javax.swing.table.DefaultTableModel;//导入包 public class LocalTableM ...

  3. 【转】python3实现自动化框架robotframework

    由于python2只更新到2020年,python3是未来的主流,为了适应技术的变化python3实现robotframework是迟早的事 1.下载最新版本的python3.7,可根据自己电脑的位数 ...

  4. kalinux实现自适用全屏、与物理主机共享文件方法

    1.执行虚拟机>安装VMware Tools菜单命令,自动挂载光驱(一般是自动挂载的,如果没有自动挂载请自行百度linux如何手动挂载光驱) 2.打开vm光驱的vmtools复制此文件到桌面: ...

  5. 【Alpha版本】冲刺阶段——Day1

    [Alpha版本]冲刺阶段--Day1 阅读目录 Alpha 阶段成员分工及任务量 团队成员贡献值的计算规则 明日任务 今日贡献量 站立式会议 TODOlist [Alpha 阶段成员分工及任务量] ...

  6. 听 Fabien Potencier 谈Symfony2 之 《What is Symfony2 ?》

    Symfoy2 是什么? PHP世界里又一广受关注的web MVC框架? Fabien Potencier 却不这么说! Fabien Potencier这样定义Symfoy2 是个什么东西: 首先, ...

  7. web项目错误—Java.util.ConcurrentMidificationException

    源代码: Iterator<String> iterator = list.iterator(); synchronized(synObject) { while(iterator.has ...

  8. SpringMVC配置字符编码过滤器CharacterEncodingFilter来解决表单乱码问题

    1.GET请求 针对GET请求,可以配置服务器Tomcat的conf\server.xml文件,在其第一个<Connector>标签中,添加URIEncoding="UTF-8& ...

  9. excel 方框打钩

    将光标定位于需要打钩的地方,选择[插入]→[符号]→[其他符号] 在弹出的符号栏里,字体一定要改成[Windings2] 然后在符号栏便可以找到现成的打钩样式,点击插入,再关闭即可 提示:如果需要打叉 ...

  10. await

    单个的task await task 多个await asyncio.wait(tasks)