首先题目要求 输出符号要求的N位数。
要求是:
1.这个N位数只能由 0,1,2,3
组成。
- 0必须出现在1前面 2必须出现在3前面
3.第一位不能为0
思想
一.
因为 0,1组合在一起,2,3组合在一起。
假设只有2个0,1,那么2,3就有N-2个。
假设有3个0,1,那么2,3就有N-3个。
......
假设有N-2个0,1,那么就有2个2,3。
因此我们把每种方案加起来就是最终方案:

假设有K个0,1,因为0不能为第一位,所以只能从剩下的N-1位中挑K位:
<math xmlns="http://www.w3.org/1998/Math/MathML"> C N − 1 K C_{^{N-1} }^{K} </math>CN−1K
2,3则从剩下的N-K位中挑选。
二.
这k位0,1内部也有多种选法。假设0是t位,那么1就是k-t位。1有多少位取决于t有多少位。
0最少有1位,1最少也有1位。
所以: <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 < = t < = k − 1 1<=t<=k-1 </math>1<=t<=k−1
而2,3同理,有 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( N − k − 1 ) (N-k-1) </math>(N−k−1) 种排法。
所以总共有 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( K − 1 ) ( N − k − 1 ) (K-1)(N-k-1) </math>(K−1)(N−k−1)种排法。
总结公式: <math xmlns="http://www.w3.org/1998/Math/MathML"> ∑ k = 2 N − 2 C N − 1 K ∗ ( K − 1 ) ( N − k − 1 ) \sum_{{^{k=2} }^{} }^{N-2} C{^{N-1} }^{K} * (K-1)(N-k-1) </math>∑k=2N−2CN−1K∗(K−1)(N−k−1)
code
因为有个排列组合: <math xmlns="http://www.w3.org/1998/Math/MathML"> C N − 1 K C_{^{N-1} }^{K} </math>CN−1K,而题目给的N最大是1000,因此我们可以用一个 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n^2) </math>O(n2)的方式算出排列组合数。方式如下:
<math xmlns="http://www.w3.org/1998/Math/MathML"> C a b = C a − 1 b − 1 + C a − 1 b C_{^{a} }^{b} = C_{^{a-1} }^{b-1} + C_{^{a-1} }^{b} </math>Cab=Ca−1b−1+Ca−1b
意思是从a的苹果里选b个苹果。
我们先从a个苹果里随便拿一个出来固定。 接着我们有两种选择。即我们可以选这个苹果1号苹果也可以不选这个1号苹果。
如果我们选了1号苹果,那剩下的选法就是从a-1个苹果中选b-1个苹果。
否则剩下的选法就是剩下的a-1个苹果中年选b个。
ok,接下来就可以写代码了。
js
#include<iostream>
using namespace std;
typedef long long LL;
const int N=1e3+7;
const int MOD=1e9+7;
int n ;
int C[N][N]; //组合数数组
int main()
{
cin >> n;
for (int i = 0; i <= n; ++i) {
for (int j = 0; j <= i; ++j) {
if (!j) C[i][j] = 1;
else C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
}
}
int res=0;
//枚举一下K
int ans = 0;
for (int k = 2; k <= n - 2; ++k) {
ans = (ans + (LL) C[n - 1][k] * (k - 1) % MOD * (n - k - 1)) % MOD;
}
cout << ans;
return 0;
}
