ccf csp 201312-4 有趣的数
首先我要再次大喊一声,组合数学大法好!
题目乍一看还有点难,想用递推还是觉得有点复杂,但是用组合数学解决就会发现非常简单。
可以这样思考:先只考虑0和1怎么放,当有a个0和b个1的时候,所有0在所有1的前面,又由于最高位不能是0,那么最高位只能是2。这样,就有a+b-1种情况(从1取到a+b-1)。假设有c个2和d 个3。一个2已经确定放在最高位了,那么现在就是c-1个2和d个3。那么把这些2和3插入已经摆好的a+b+1个数里面有多少可能呢?其实这就相当于c+d-1个相同的球(思考为什么是相同的而不是不同的)放到a+b+1个(最高位之前的位置不用放了)相同的盒子里,且允许空盒的情况,即C(a+b+1+c+d-1-1,c+d-1),然后2和3一共有c+d个,又有c+d-1种可能。
所以最后总的可能数就是C(n-1,c+d-1)*(c+d-1)*(a+b-1),只需要从2到n-2遍历c+d再累加就行了
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define MAX 1010
#define LL long long
using namespace std;
const LL MOD=1000000007;
LL n,s[MAX][MAX];
void init(){
for(int i=1;i<MAX;i++)
s[i][i]=1,s[i][1]=i,s[i][0]=1;
for(int i=2;i<MAX;i++){
for(int j=1;j<i;j++){
s[i][j]=(s[i-1][j-1]+s[i-1][j])%MOD;
}
}
}
int main(){
init();
cin>>n;
LL ans=0;
for(int i=2;i<=n-2;i++){
ans=(ans+s[n-1][i-1]*(i-1)*(n-i-1))%MOD;
}
cout<<ans<<endl;
return 0;
}