标签:class 最小 nbsp 输入格式 div style init namespace temp
今天刷CCF题的时候刷到了这题,貌似是第四题,但鄙人认为它根本够不上这个难度,放第二题差不多。
我看见网上其他人的题解,用的都是dp、递推之类的东西,讨论了很多。但我觉得这些题解把题复杂化了。其实只要用到高中数学的组合数就够了。
首先,易知数的首位必定是2;我们接下来只要往剩余n-1个位置里放0、1、2、3就行。
其次,由约束条件知只有只有0、1之间和2、3之间有约束,而放置0/1和2/3的数位之间是毫无关系的,所以可以将它们分开计算。设有i位中为0或1,则由约束条件知0必然都在最前面,设有j个0,则1≤j≤i-1(保证0和1都有),j有i-1种。再考虑只放2和3的位,设有p位,由于第一位已经是2了,所以只要p位中至少有1个3,故1≤p≤(n-1)-2,而在这p位中3都集中在后面,故有3的个数p种可能。此时01和23的个数的组合一共(i-1)*p=(i-1)*(n-1-i)种。
接下来,从n-1位中选出i位,把0、1放入。因为0、1的次序和数量都已知,所以选择是无序的,共Cin-1 种。故当有i位放0或1时有Cin-1 *(i-1)*(n-i-1)种。
所以答案是∑Cin-1 *(i-1)*(n-i-1),其中2≤i≤(n-1)-1
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #define maxn 1010 4 #define ll long long 5 #define mod 1000000007 6 using namespace std; 7 ll c[maxn][maxn]; 8 int n; 9 void init()//预处理组合数 10 { 11 for (int i = 0; i <= n; i++) 12 { 13 for (int j = 0; j <= i; j++) 14 { 15 if (j == 0 || j == i) 16 c[i][j] = 1; 17 else 18 c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod; 19 } 20 } 21 } 22 int main() 23 { 24 ll ans = 0; 25 scanf("%d", &n); 26 init(); 27 ll temp; 28 for (int i = 2; i <= (n-1)-1; i++)//i位为1或0 29 { 30 temp = c[n - 1][i]; 31 temp *= (i-1); 32 temp %= mod; 33 temp *= (n - 1 - i ); 34 temp %= mod; 35 ans += temp; 36 ans %= mod; 37 } 38 printf("%lld", ans); 39 return 0; 40 }
标签:class 最小 nbsp 输入格式 div style init namespace temp
原文地址:https://www.cnblogs.com/yangyi2120/p/14617642.html