题意:求所有长度为\(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. object base基类分析

    uvm_object,是所有uvm data和hierarchical class的基类,实现了copy,compare,print,record之类的函数 扩展类中必须实现create和get_ty ...

  2. 01 while 循环输入1 2 3 4 5 6 8 9 10

      start = 1while True:    if start == 7:        start += 1        continue    print(start)    start ...

  3. mybatis源码解析2---SqlSessionFactoryBuilder、SqlSessionFactory解析

    1.先看一个mybatis最简单的Demo String resource = "mybatis-config.xml"; //1.流形式读取mybatis配置文件 InputSt ...

  4. 实现Winform 跨线程安全访问UI控件

    在多线程操作WinForm窗体上的控件时,出现“线程间操作无效:从不是创建控件XXXX的线程访问它”,那是因为默认情况下,在Windows应用程序中,.NET Framework不允许在一个线程中直接 ...

  5. 新做了块avr开发板--tft屏研究用

    2010-05-04 14:03:00 测试效果不错,使用也方便.

  6. .NET 常用ORM之iBatis

    ibatis 一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目,到后面发展的版本叫MyBatis但都是指的同一个东西.最初侧重 ...

  7. Deeplearning 两层cnn卷积网络详解

    https://blog.csdn.net/u013203733/article/details/79074452 转载地址: https://www.cnblogs.com/sunshineatno ...

  8. 在win10下安装eclipse

    1.在官网下载jdk.目前最新版本为jdk8. http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-21331 ...

  9. hihocoder [Offer收割]编程练习赛8

    第一次做这种比赛,被自己坑的好惨... A.这道题的关键其实是如果有k和n满足kD+F>nL>kD则不能走无限远,分支看似难整理,其实比较简单,F>L根本就不用算了,明摆着就是Bsi ...

  10. [VS] - "包含了重复的“Content”项。.NET SDK 默认情况下包括你项目中的“Content”项。

    copy to :http://www.cnblogs.com/jinzesudawei/p/7376916.html VS 2017 升级至  VS 2017 v15.3 后,.Net Core 1 ...