题目
在集合S=[1∼n]S=[1\sim n]S=[1∼n]中选出mmm个子集,满足三点性质:
- 所有选出的mmm个子集都不能为空。
- 所有选出的mmm个子集中,不能存在两个完全一样的集合。
- 所有选出的mmm个子集中,1到nnn每个元素出现的次数必须是偶数。
问有多少种不同的方法,两个子集 a 和 b 同种当且仅当将 a 的子集重新排列后可以得到 b
分析
首先作为一道黑题,它还是具有它的难度的,因为是真的恶心。
首先不同就是个幌子,只要答案除以m!m!m!的阶乘就可以了。
设dp[i]dp[i]dp[i]表示前iii个合法集合的方法数
第二,考虑容斥,若是偶数,那么第iii个是唯一的,也就是前i−1i-1i−1个出现奇数次的,所以总共方案是P2n−1i−1P^{i-1}_{2^n-1}P2n−1i−1
然后,非空,那么当第iii个集合为空时,那么方案数是dp[i−1]dp[i-1]dp[i−1]
接着不能存在完全一样的集合,若jjj与iii重复,那么剩下的i−2i-2i−2个子集是合法方案,jjj有i−1i-1i−1种取值,第jjj个子集可以有2n−1−(i−2)2^n-1-(i-2)2n−1−(i−2)种方案,所以也就是dp[i−2]×(i−1)×(2n−i+1)dp[i-2]\times (i-1)\times (2^n-i+1)dp[i−2]×(i−1)×(2n−i+1)
综上所述,dp[i]=P2n−1i−1−dp[i−1]−dp[i−2]×(i−1)×(2n−i+1)dp[i]=P^{i-1}_{2^n-1}-dp[i-1]-dp[i-2]\times (i-1)\times (2^n-i+1)dp[i]=P2n−1i−1−dp[i−1]−dp[i−2]×(i−1)×(2n−i+1)
dp[0]=1,dp[1]=0dp[0]=1,dp[1]=0dp[0]=1,dp[1]=0(是真的骚)
代码
#include <cstdio>
#define rr register
using namespace std;
typedef long long ll;
const ll mod=100000007;
inline ll ksm(ll x,ll y){
rr ll ans=1;
for (;y;y>>=1,x=x*x%mod)
if (y&1) ans=ans*x%mod;
return ans;
}
signed main(){
rr int n,m; rr ll dp=0;
scanf("%d%d",&n,&m);
rr ll mi=ksm(2,n),dp1=0,dp2=1,c=1,jc=1;
for (rr int i=2;i<=m;++i){
rr ll t=mi-i+1+mod; c=c*t%mod,jc=jc*i%mod;
dp=((c-dp1-dp2*(i-1)%mod*t%mod)+mod)%mod,dp2=dp1,dp1=dp;
}
return !printf("%lld",dp*ksm(jc,mod-2)%mod);
}