其他分享
首页 > 其他分享> > P3214 [HNOI2011] 卡农 (dp +排列计数 正难则反)

P3214 [HNOI2011] 卡农 (dp +排列计数 正难则反)

作者:互联网

 

题目传送门

题目大意:

给定两个数 \(n , m\) ,在集合 \(S = {1,2...n}\) 中选取 \(m\) 个非空子集,使得子集不重复并且子集中的每个元素出现偶数次,求出满足上述条件的方案数。
假设 \(a\) 为 \(\{\{1,2\},\{2,3\}\}\),\(b\) 为 \(\{\{2,3\},\{1,2\}\}\),那么 \(a\) 与 \(b\) 为重复情况。(笔者定义这种情况为假相同)

题目分析:

代码实现:

我们只需要处理出 \(2^n-1\) , \(m!\), \(A_{2^n-1}^i\)即可,最后处理一下逆元,用 \(f_m * \frac{1}{m!}\) 即可

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e8 + 7;
const int M = 1e6 + 7; 
int f[M] , A[M];
int Pow(int a, int b) {
	int ans = 1;
	while(b) {
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
		b >>= 1;	
	}
	return ans;
}	
signed main () {
	int n , m; cin >> n >> m;
	int _2 = 1;
	for(int i = 1; i <= n; ++ i) _2 = _2 * 2 % mod;
	_2 = (_2 + mod - 1) % mod;
	A[0] = 1;
	int jc = 1;
	for(int i = 1; i <= m; ++ i) A[i] = A[i - 1] * ((_2 - i + 1 + mod) % mod) % mod , jc = jc * i % mod;
	f[f[1] = 0] = 1;
	for(int i = 2; i <= m; ++ i) f[i] = (A[i - 1] - f[i - 1] + mod - f[i - 2] * (i - 1) % mod * (_2 - i + 2 + mod) % mod + mod) % mod;
	cout << f[m] * Pow(jc , mod - 2) % mod;
}

[========]

完结!

标签:方案,int,选取,偶数,P3214,HNOI2011,子集,我们,卡农
来源: https://www.cnblogs.com/Love-yx/p/16660134.html