传送门: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); }