zoukankan      html  css  js  c++  java
  • Codeforces 285 E. Positions in Permutations

    ## [$>Codeforces space 285 E. Positions in Permutations<$](http://codeforces.com/problemset/problem/285/E)

    题目大意 : 定义一个长度为 (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] imes(n-k)!)

    考虑要求 (Ans_k =) 恰好有 (k) 个元素是好的方案数,那么有 (Ans_k = sum_{i = k}^{n} (-1)^{i-k} imes C_i^k imes 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;
    }
    
  • 相关阅读:
    OSX安装nginx和rtmp模块(rtmp直播服务器搭建)
    用runtime来重写Coder和deCode方法 归档解档的时候使用
    Homebrew安装卸载
    Cannot create a new pixel buffer adaptor with an asset writer input that has already started writing'
    OSX下面用ffmpeg抓取桌面以及摄像头推流进行直播
    让nginx支持HLS
    iOS 字典转json字符串
    iOS 七牛多张图片上传
    iOS9UICollectionView自定义布局modifying attributes returned by UICollectionViewFlowLayout without copying them
    Xcode6 iOS7模拟器和Xcode7 iOS8模拟器离线下载
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9368346.html
Copyright © 2011-2022 走看看