赞
踩
给定一个1~N的排列a[i],每次将相邻两个数相加,得到新序列,再对新序列重复这样的操作,显然每次得到的序列都比上一次的序列长度少1,最终只剩一个数字。
例如:
3 1 2 4
4 3 6
7 9
16
现在如果知道N和最后得到的数字sum,请求出最初序列a[i],为1~N的一个排列。若有多种答案,则输出字典序最小的那一个。数据保证有解。
输入格式
第1行为两个正整数n,sum
输出格式
一个1~N的一个排列
样例输入
4 16
样例输出
3 1 2 4
数据规模和约定
0<n<=10
示例分析:
a[4] = {3,1,2,4};
初始值:a[0] = 3, a[1] = 1, a[2] = 2, a[3] = 4;
第一次相加:a[0]+a[1], a[1]+a[2], a[2]+a[3];
第二次相加:a[0]+2*a[1]*a[2], a[1]+2*a[2]+a[3];
第三次相加:a[0]+3*a[1]+3*[2]+a[3]
从示例的分析可以看出最终的和就是各个元素乘某一个数然后再相加的结果:
观察最后结果的系数,发现其实它们各自的系数为1,3,3,1;
即C(0,3),C(1,3),C(2,3),C(3,3);
即C(0,4-1),C(1,4-1),C(2,4-1),C(3,4-1);
推广到n,最后的和:temp = a[0]*C(0,n-1) + a[1]*C(1,n-1) + ... +a[n-1]*C(n-1,n-1);
判断temp 是否与输入的 sum 相等,若相等,则为其中一种解。
根据题目的提示,我们可以知道,同一种输入可能会有多种解,题目要求输出字典序最小的那一个,那么我们可以利用C++提供的全排列函数next_permutation,该函数已经将所有元素可能的排列组合按顺序排列,第一个满足temp == sum 的数组,即为题目所求的排列。
- #include <iostream>
- #include <algorithm>
- #include <math.h>
- #include <vector>
-
- using namespace std;
-
- //求C(m,n)
- int c_Fun(int n, int m) {
- int i = 0;
- int ans_n = 1, ans_m = 1, ans_nm = 1;
- for (i = 2; i <= n; i++) {
- ans_n = ans_n * i;
- }
- for (i = 2; i <= m; i++) {
- ans_m = ans_m * i;
- }
- for (i = 2; i <= n - m; i++) {
- ans_nm = ans_nm * i;
- }
- return ans_n / (ans_m * ans_nm);
- }
-
- int main() {
- int n = 0;
- cin >> n;
- int sum = 0;
- cin >> sum;
-
- //用容器存储1~N
- vector<int> vec;
- for (int i = 1; i <= n; i++) {
- vec.push_back(i);
- }
-
- do{
- int temp = 0;
- for (int i = 0; i < n; i++) {
- temp += c_Fun(n-1, i)*vec[i];
- }
- if (sum == temp){
- for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
- cout << *it << " ";
- }
- break;//找到一组解后,直接退出
- }
- }while (next_permutation(vec.begin(), vec.end()));
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。