题目大意:就是农夫和这只牛又杠上了(怎么老是牛啊,能换点花样吗),给出一行数(从1到N),按杨辉三角的形式叠加到最后,可以得到一个数,现在反过来问你,如果我给你这个数,你找出一开始的序列(可能存在多个序列,输出字典序最小的那个)。
这一题首先你要看懂原文的那个1到N是什么意思,就是那一行数只能是1到N,而不是1到10(我一开始犯了这个愚蠢的错误,导致枚举到风扇呼呼的转),如果是这样给你,那么这道题就很简单啦,就直接是用next_permutation枚举所有的序列就可以了,然后找出字典序最小的那个。
但是这里有个问题,如果你真的找出一个然后去比较字典序,那真是太慢了,一开始直接暴力枚举+测试一个一个字串的速度
看到了没?差点就超时了,这个还是我直接用二维数组+迭代的,换暴力DFS直接就超时了吧。
其实这个时候我们可以看到,这样做我们忽略了一个事实,如果字串是顺序的,我们可以回想一下我们的枚举是怎枚举的(STL里面也是这么写的),是一个循环从1到N,然后找到没有被标记的数,然后进去递归,这样的话,其实就隐含了字典序排序了,如果我们一开始按照12345678...这样排列下来,那么找到的第一个字串,肯定是字典序最小的,所以,我们找到之后直接break就可以了
1 #include <iostream> 2 #include <functional> 3 #include <algorithm> 4 5 using namespace std; 6 7 static int set[11], tmp[11]; 8 static int sum, length; 9 10 void enum_string(const int,const int); 11 bool scmop(void); 12 13 int main(void) 14 { 15 while (~scanf("%d%d", &length, &sum)) 16 { 17 for (int i = 1; i <= length; i++) 18 tmp[i - 1] = i; 19 if (length == 1 && tmp[0] == sum) 20 { 21 for (int i = 0; i < length; i++) 22 printf("%d ", tmp[i]); 23 printf("\n"); 24 continue; 25 } 26 do{ 27 for (int i = 0; i < length - 1; i++) 28 set[i] = tmp[i] + tmp[i + 1]; 29 for (int i = length - 2; i >= 0; i--) 30 { 31 for (int j = 0; j < i; j++) 32 set[j] = set[j] + set[j + 1]; 33 } 34 if (set[0] == sum) 35 { 36 for (int i = 0; i < length; i++) 37 printf("%d ", tmp[i]); 38 printf("\n"); 39 break; 40 } 41 } while (next_permutation(tmp, tmp + length)); 42 43 } 44 return 0; 45 }
还没完,开始我不是说了吗?这一题是按照杨辉三角的形式展开的,我们知道杨辉三角的每一行的数都是组合数Ckn,那么在数学上,杨辉三角的加法一行数的相加次数相当于这个Ckn,
也就是说,我们只用把这一行的数乘以Ckn就可以得到结果了,这样做会更快
#include <iostream> #include <functional> #include <algorithm> using namespace std; static int set_sum, tmp[11], Cn[11]; static int sum, length; void enum_string(const int, const int); bool scmop(void); void Cal_Cn(const int); int main(void) { while (~scanf("%d%d", &length, &sum)) { for (int i = 1; i <= length; i++) tmp[i - 1] = i; memset(Cn, 0, sizeof(Cn)); Cal_Cn(length); if (length == 1 && tmp[0] == sum) { for (int i = 0; i < length; i++) printf("%d ", tmp[i]); printf("\n"); continue; } do{ set_sum = 0; for (int i = 0; i < length; i++) set_sum += Cn[i] * tmp[i]; if (set_sum == sum) { for (int i = 0; i < length; i++) printf("%d ", tmp[i]); printf("\n"); break; } } while (next_permutation(tmp, tmp + length)); } return 0; } void Cal_Cn(const int length) { Cn[0] = 1; for (int j = 1; j < length; j++) { Cn[j] = length - 1; for (int k = 2; k <= j; k++) Cn[j] *= (length - k); for (int k = 1; k <= j; k++) Cn[j] /= k; } }
最后,32ms
时间: 2024-10-23 21:00:03