计数题都好神啊 ~
但其实这道题也算是一个套路题吧,只是我没分析出来.....
code:
#include <cstdio>
#include <algorithm>
#define N 18
#define ll long long
#define mod 1000000007
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int bin[N],f[N][1<<N],fac[1<<N],inv[1<<N],a[N];
int qpow(int x,int y)
{
int tmp=1;
for(;y;y>>=1,x=(ll)x*x%mod)
if(y&1) tmp=(ll)tmp*x%mod;
return tmp;
}
int C(int x,int y) { if(x<y) return 0; return (ll)fac[x]*inv[y]%mod*inv[x-y]%mod; }
int count(int x)
{
int c=0;
while(x) { if(x&1) ++c; x>>=1; }
return c;
}
int main()
{
// setIO("input");
int i,j,n,m;
scanf("%d%d",&n,&m);
bin[0]=fac[0]=inv[0]=1;
for(i=1;i<=n;++i) bin[i]=bin[i-1]<<1;
for(i=1;i<=bin[n];++i) fac[i]=(ll)fac[i-1]*i%mod,inv[i]=qpow(fac[i],mod-2);
for(i=1;i<=m;++i) scanf("%d",&a[i]);
sort(a+1,a+1+m);
f[m+1][0]=1;
int cnt=0;
for(i=m;i>=1;--i)
{
for(j=0;j<bin[n];++j)
{
f[i][j]=(ll)(f[i][j]+f[i+1][j])%mod;
int t=bin[n]-1-j; // 共有 t 个空位置
for(int k=0;bin[k]<bin[n];++k)
{
if(j&bin[k]||!f[i+1][j]) continue;
(f[i][j|bin[k]]+=((ll)f[i+1][j]*C(t-a[i]+1,bin[k]-1)%mod*fac[bin[k]]%mod)%mod)%=mod;
}
}
}
int ans=0;
for(i=0;i<bin[n];++i)
{
int d=(count(i)&1)?mod-1:1;
ans=(ll)(ans+(ll)f[1][i]*fac[bin[n]-1-i]%mod*d%mod)%mod;
}
ans=(ll)ans*bin[n]%mod;
printf("%d\n",ans);
return 0;
}