蓝桥杯 数字游戏 C++

给定一个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;
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_56318237

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值