传送门:http://blog.csdn.net/visit_world/article/details/51090964
dp其中一维解释一下,表示可以放且必须放的一个位置
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define P 1000000007
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
int maxn=1000000;
ll fac[1000005],inv[1000005];
inline void Pre()
{
fac[0]=1;
for (int i=1;i<=maxn;i++)
(fac[i]=fac[i-1]*i)%=P;
inv[1]=1;
for (int i=2;i<=maxn;i++)
(inv[i]=(P-P/i)*inv[P%i])%=P;
inv[0]=1;
for (int i=1;i<=maxn;i++)
(inv[i]*=inv[i-1])%=P;
}
inline ll C(int n,int m){
return ((fac[n]*inv[m])%P*inv[n-m])%P;
}
ll f[2][3205][41];
int d[45],m,n,sum;
int main()
{
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
Pre();
read(m), read(n);
for (int i = 1; i <= n; ++i)
read(d[i]),--d[i],sum+=d[i]<<1;
sort(d+1,d+n+1);
int t=0;
f[t][0][1]=1;
for (int i=n;i;i--,t^=1)
{
memset(f[t^1],0,sizeof(f[t^1]));
int v=d[i];
for (int j=0;j<=sum;j++)
for (int k=1;k<=n;k++)
if (f[t][j][k])
{
ll x=f[t][j][k];
(f[t^1][j+v*2][k+1]+=x*k%P)%=P;
(f[t^1][j+v][k]+=x*k*2%P)%=P;
(f[t^1][j][k-1]+=x*k%P)%=P;
}
}
ll ret=0;
for (int j=min(sum,m-n);~j;j--)
if (f[t][j][0])
(ret+=f[t][j][0]*C(m-j,n)%P)%=P;
printf("%lld\n",ret);
}