1. 程式人生 > 其它 >Shaass and Lights CodeForces - 294C

Shaass and Lights CodeForces - 294C

原題連結
考察:組合數學
思路:

  我們不必模擬每次具體去掉什麼.因為去掉的蠟燭只能在熄滅的蠟燭左右倆側.對於區間\(2\),每次在左右端點選一個去掉,方法數是\(2^{8-4-1-1}\).但是區間1,3是特殊的,因為只有一種方法.
  計算完區間內部的方法後,就是計算區間之間的方法數.這裡不能用插空法.是先有\(n-m\)個位置,將位置填滿的計算方法.

Code

#include <iostream> 
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1010,M = 1000000007; 
int nums[N],n,m,C[N][N];
void init()
{
	for(int i=0;i<N;i++)
	  for(int j=0;j<=i;j++)
	    if(!j) C[i][j] = 1;
		else C[i][j] = ((LL)C[i-1][j-1]+C[i-1][j])%M; 
}
int qsm(int a,int k,int m)
{
	if(k<0) return 1;
	int res = 1;
	while(k)
	{
		if(k&1) res = (LL)res*a%m;
		a = (LL)a*a%m;
		k>>=1;
	}
	return res;
}
int main()
{
	scanf("%d%d",&n,&m);
	init();
	int res = 1,now = n-m;
	if(n==m) {puts("1");return 0;}
	for(int i=1;i<=m;i++) scanf("%d",&nums[i]);
	sort(nums+1,nums+m+1);
	for(int i=2;i<=m;i++)
	{
		int len = nums[i]-nums[i-1]-1;
		res = (LL)res*qsm(2,len-1,M)%M;
	}
	nums[m+1] = n+1;
	for(int i=1;i<=m+1;i++)
	{
		res = (LL)res*C[now][nums[i]-nums[i-1]-1]%M;
		now-=nums[i]-nums[i-1]-1;
	}
	printf("%d\n",res);
	return 0;
}