Description
![]()
Input
Output
Sample Input
Sample Output
HINT
Source
Day2
首先题目里说是无序的,但是不要管它,我们先把它看成有序的,最后除以一个
m!
即可。我们考虑补集转换,首先所有的子集个数应该是
2n−1
,我们定义
f[i]
为挑选
i
个片段的合法的方案数,此时总数应该是
1、如果前
2、如果根据前
i−1
个确定出来的第
i
个集合和前面的某一个重复,这样肯定是不合法的。
因为考虑顺序,所以那个和第
最后在乘上一个
m!
关于
mod
的逆元即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cctype>
typedef long long ll;
using namespace std;
const int mod=100000007;
const int M=1000010;
ll f[M],A[M],n,m,ans;
void in(ll &x)
{
char t=getchar();int f=1;x=0;
while(!isdigit(t)){if(t=='-')f=-1;t=getchar();}
while(isdigit(t)){x=x*10+t-48;t=getchar();}
x*=f;
}
ll power(ll a,ll b)
{
ll ans=1;
for (;b;b>>=1,a=(a*a)%mod)
if (b&1) ans=(ans*a)%mod;
return ans;
}
void work()
{
A[0]=1;
for (int i=1;i<=m;++i) A[i]=(A[i-1]*((ans-i+1+mod)%mod))%mod;
}
int main()
{
in(n),in(m);
ans=power(2,n);--ans;
if (ans<0) ans+=mod;
work();
for (int i=3;i<=m;++i)
f[i]=((A[i-1]-f[i-1]-(f[i-2]*(i-1)%mod*(ans-(i-2)))%mod)+mod)%mod;
ans=1;
for (int i=2;i<=m;++i) ans=(ans*i+mod)%mod;
f[m]=(f[m]*power(ans,mod-2)%mod+mod)%mod;
cout<<(f[m]+mod)%mod;
return 0;
}