Description
给出一排灯,用
01
表示灯的开关状态,
0
表示灯关,
Input
第一行两个整数
n,m
表示灯的数量和打开灯的数量,之后输入
m
个整数表示这
Output
输出方案数,结果模 109+7
Sample Input
3 1
1
Sample Output
1
Solution
假设这些开着的灯的位置为 a1<a2<...<am ,对于两端的没开的灯,只能从 a1 开始往前开,从 am 开始往后开,而中间的没开的灯,可以从 ai 往 ai+1 开,也可以从 ai+1 往 ai 开,先考虑开 ai ~ ai+1 这段没开的 ai+1−ai−1 个灯,每次可以从两边选一个开开,只有一个的时候只能开这个,故方案数为 2min(ai+1−ai−2,0) ,而每一段相互独立,每次可以选择一段去开一个灯,方案数为多项式系数 (a1−1a2−a1−1n−m...an−an−1−1n−an)
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=1005;
#define mod 1000000007
int fact[maxn],inv[maxn],f2[maxn];
void init(int n=1000)
{
f2[0]=1;
for(int i=1;i<=n;i++)f2[i]=2*f2[i-1]%mod;
fact[0]=1;
for(int i=1;i<=n;i++)fact[i]=(ll)i*fact[i-1]%mod;
inv[1]=1;
for(int i=2;i<=n;i++)inv[i]=mod-(ll)(mod/i)*inv[mod%i]%mod;
inv[0]=1;
for(int i=1;i<=n;i++)inv[i]=(ll)inv[i-1]*inv[i]%mod;
}
int n,m,a[maxn];
int main()
{
init();
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=m;i++)scanf("%d",&a[i]);
sort(a+1,a+m+1);
int ans=1;
for(int i=1;i<m;i++)ans=(ll)ans*f2[max(a[i+1]-a[i]-2,0)]%mod;
ans=(ll)ans*fact[n-m]%mod;
a[0]=0,a[m+1]=n+1;
for(int i=1;i<=m+1;i++)ans=(ll)ans*inv[a[i]-a[i-1]-1]%mod;
printf("%d\n",ans);
}
return 0;
}