## [$>Codeforces \space 285 E. Positions in Permutations

题目大意 : 定义一个长度为 \(n\) 的排列中第 \(i\) 个元素是好的,当且仅当 \(i\)在排列中的位置 \(p_i\) 满足 \(|i - p_i| = 1\), 给出 \(n, k\) 求长度为 \(n\) 的排列中恰好有 \(k\) 个元素是好的方案数

$1 \leq n \leq 1000, 0 \leq k \leq n $

解题思路 :

观察发现,直接求出答案貌似十分困难,不妨先 \(dp\) 出至少 \(k\) 个元素是好的方案数,然后再通过 容斥/反演 来解决

至少有 \(k\) 个元素是好的方案数等价于有 \(k\) 个位置存在匹配 \(|i-p_i| = 1\) ,剩余元素随便排列的方案数

设 \(f[i][j][0/1][0/1]\) 表示前 \(i\) 个元素和前 \(i\) 个位置产生了 \(j\) 对匹配,第 \(i\) 个元素和第 \(i\) 个位置是否已经被匹配的方案数

转移很显然,只需要枚举 \(i-1\) 上的元素和位置是否能和 \(i\) 上的元素和位置产生匹配即可

设 \(F(k)\) 表示至少有 \(k\) 个是好的方案数,那么 \(k = f[n][k] \times(n-k)!\)

考虑要求 \(Ans_k =\) 恰好有 \(k\) 个元素是好的方案数,那么有 \(Ans_k = \sum_{i = k}^{n} (-1)^{i-k} \times C_i^k \times F(i)\)

这个和最基础的容斥又有所不一样,简单的考虑,对于 \(i > k\) 的每一个 \(Ans_i\) ,其中任意选 \(k\) 个好元素都能更新到 \(Ans_k\) ,所以方案数是 \(C_i^k\) ,在容斥进行补集转换的时候需要乘上这个系数

往复杂了讲,这个涉及到容斥原理最本质的在集合上的运算,之前的 \(i\) 将表示所有大小为 \(i\) 的集合,那么每一个大小为 \(i\) 的集合在算到 \(Ans_k\) 的过程中都产生了 \(C_i^k\) 个不同的大小为 \(k\) 的集合

当中的具体证明可以看近年集训队论文,或者我的好友 cly_none的博客

考虑到前面算 \(F(i)\) 的时候,两个不同的匹配方案可能会对应到同一个排列,这里等价于每一个大小为 \(i\) 的集合,选 \(k\) 个好元素得到的新集合可能相同,所以两个重复计数恰好抵消了

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
#define N (2005)
#define int ll
const int Mod = 1000000007;
int js[N], inv[N], f[N][N][2][2], g[N], n, k;
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 i){ return js[n] * inv[i] % Mod * inv[n-i] % Mod; }
main(){
read(n), read(k), f[0][0][0][0] = 1, js[0] = inv[0] = 1;
for(int i = 1; i <= n; i++){
js[i] = js[i-1] * i % Mod;
inv[i] = pow(js[i], Mod - 2);
}
for(int i = 1; i <= n; i++)
for(int j = 0; j <= n; j++){
(f[i][j][0][0] += f[i-1][j][0][0] + f[i-1][j][1][1]) %= Mod;
(f[i][j][0][0] += f[i-1][j][0][1] + f[i-1][j][1][0]) %= Mod;
if(j >= 1 && i > 1){
(f[i][j][1][0] += f[i-1][j-1][1][0] + f[i-1][j-1][0][0]) %= Mod;
(f[i][j][0][1] += f[i-1][j-1][0][1] + f[i-1][j-1][0][0]) %= Mod;
}
if(j >= 2 && i > 1) (f[i][j][1][1] += f[i-1][j-2][0][0]) %= Mod;
}
for(int i = 0; i <= n; i++){
int res = 0;
(res += f[n][i][0][0] + f[n][i][1][0]) %= Mod;
(res += f[n][i][0][1] + f[n][i][1][1]) %= Mod;
g[i] = res * js[n-i] % Mod;
}
int ans = 0;
for(int i = k; i <= n; i++){
int p = ((i - k) & 1) ? Mod - 1 : 1;
(ans += C(i, k) * p % Mod * g[i] % Mod) %= Mod;
}
cout << ans << endl;
return 0;
}

Codeforces 285 E. Positions in Permutations的更多相关文章

  1. 【CF285E】Positions in Permutations(动态规划,容斥)

    [CF285E]Positions in Permutations(动态规划,容斥) 题面 CF 洛谷 题解 首先发现恰好很不好算,所以转成至少,这样子只需要确定完一部分数之后剩下随意补. 然后套一个 ...

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

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

  3. Codeforces 285E - Positions in Permutations(二项式反演+dp)

    Codeforces 题目传送门 & 洛谷题目传送门 upd on 2021.10.20:修了个 typo( 这是一道 *2600 的 D2E,然鹅为啥我没想到呢?wtcl/dk 首先第一步我 ...

  4. CF285 E Positions in Permutations——“恰好->大于”的容斥和允许“随意放”的dp

    题目:http://codeforces.com/contest/285/problem/E 是2018.7.31的一场考试的题,当时没做出来. 题解:http://www.cnblogs.com/y ...

  5. 【codeforces 501D】Misha and Permutations Summation

    [题目链接]:http://codeforces.com/problemset/problem/501/D [题意] 给你两个排列; 求出它们的字典序num1和num2; 然后让你求出第(num1+n ...

  6. Educational Codeforces Round 32 Almost Identity Permutations CodeForces - 888D (组合数学)

    A permutation p of size n is an array such that every integer from 1 to n occurs exactly once in thi ...

  7. Codeforces 888D: Almost Identity Permutations(错排公式,组合数)

    A permutation \(p\) of size \(n\) is an array such that every integer from \(1\) to \(n\) occurs exa ...

  8. codeforces 285 D. Permutation Sum 状压 dfs打表

    题意: 如果有2个排列a,b,定义序列c为: c[i] = (a[i] + b[i] - 2) % n + 1 但是,明显c不一定是一个排列 现在,给出排列的长度n (1 <= n <= ...

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

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

随机推荐

  1. 省队集训 Day1 残缺的字符串

    [题目大意] 双串带通配符匹配. $|S|, |T| \leq 5 * 10^5$ TL: 2s [题解] 参考bzoj 4503 可以设计如下函数 A[i] * B[i] * (A[i] - B[i ...

  2. 省队集训Day1 过河

    [题目大意] 小奇特别喜欢猪,于是他养了$n$只可爱的猪,但这些猪被魔法猪教会了魔法,一不看着某些猪就会自己打起来. 小奇要带着他的猪讨伐战狂,路途中遇到了一条河.小奇找到了一条船,可惜这条船一次只能 ...

  3. CSS 竖线颜色渐变

    <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"& ...

  4. embed标签 阻止点击事件 让父元素处理点击事件

    由于规定页面显示的PDF文件要有固定大小,使得页面风格统一 最开始发现了CSS样式pointer-events 写出如下代码,在360急速浏览器急速模式中访问可在点击PDF控件时可跳转页面 <a ...

  5. Python 16进制与字符串的转换

    电脑上装了Python2.7和3.3两个版本,平时运行程序包括在Eclipse里面调试都会使用2.7,但是由于某些原因在cmd命令行中输入python得到的解释器则是3.3, 一直没对此做处理,因为这 ...

  6. 【Sqlite3】sqlite_sequence表(转)

    sqlite_sequence表也是SQLite的系统表.该表用来保存其他表的RowID的最大值.数据库被创建时,sqlite_sequence表会被自动创建.该表包括两列.第一列为name,用来存储 ...

  7. 很重要的处理项目url[www]

    http://www.xdowns.com/soft/10/57/2013/Soft_113319.html https://github.com/TricksterGuy/Morphan http: ...

  8. 简单的自动化运维工具(shell+except+whiptail+功能模块化函数+循环)

    简单的自动化运维工具(shell+except+whiptail+功能模块化函数+循环) http://www.cnblogs.com/M18-BlankBox/p/5881700.html

  9. tcp窗口机制(写的最简单精炼的文章)

    tcp窗口机制(写的最简单精炼的文章) http://blog.csdn.net/occupy8/article/details/48468445

  10. angular数据绑定---js全局学习

    <!DOCTYPE html> <html ng-app> <head> <title>Simple app</title> </he ...