排列组合 Shaass and Lights:CodeForces - 294C

题目 Shaass and Lights:CodeForces - 294C

题意

有N(N<=1000)盏灯,一开始都是暗的,只有其中M盏是亮的。Shaass想要点亮所有的灯,但是每次只能点亮已经点亮的灯的相邻的两盏灯中的一盏。现在Shaass想知道总共有多少种方法点亮所有的灯。结果mod 1e9+7。

思路

把这些灯看做线段的话,亮着的灯将线段切分成一个一个小线段。用样例3举例"...#...#...",被分割成3个线段,不妨命名为ABC。那么AAABBBCCC就是一种开灯方式。这种排列组合总数为\(\frac{9!}{3!3!3!}\),对于B线段本身来说总共有\(2^{3-1}\)种选法。A和C特殊一点,因为是边界线段,有只有一种方案。所以总方案数为\(\frac{9!}{3!3!3!}*1*2^{3-1}*1\)

代码

#include<cstdio>
#include<algorithm>
#define M 1010
#define MOD 1000000007
using namespace std;
int n,m,a[M],s;
long long pw[M],c[M][M],ans=1;
int main()
{
	pw[0]=pw[1]=1;for(int i=2;i<M;i++) pw[i]=2*pw[i-1]%MOD;
	for(int i=0;i<M;i++) 
  	for(int j=0;j<=i;j++) 
	c[i][j]=((!i||!j||i==j)?1:c[i-1][j]+c[i-1][j-1])%MOD;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)scanf("%d",&a[i]);
	sort(a+1,a+m+1);s=n-m;
	for(int i=2;i<=m;i++){
		int w=a[i]-a[i-1]-1;
		ans=ans*c[s][w]%MOD*pw[w]%MOD;
		s-=w;
	}
	ans=ans*c[s][a[1]-1]%MOD;
	printf("%lld",ans);
}
posted @ 2017-11-03 09:33  xjdx  阅读(154)  评论(0)    收藏  举报