杨辉三角
1.定义:百度百科_杨辉三角
ps:其中的有几个性质特别有意思
2.我们可以利用杨辉三角的一些简单知识来解决问题
如下问题:
题目描述
写出一个11至NN的排列a_iai,然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少1,直到只剩下一个数字位置。下面是一个例子:
3,1,2,4
4,3,6
7,9
16
最后得到16这样一个数字。
现在想要倒着玩这样一个游戏,如果知道N,知道最后得到的数字的大小sum,请你求出最初序列a,为1至N的一个排列。若答案有多种可能,则输出字典序最小的那一个。
输入输出格式
输入格式:
两个正整数n,sum。
输出格式:
输出包括1行,为字典序最小的那个答案。
1.分析:
对于这个问题:我们先看n的序列。
如果所这一行的n个数是a,b,c....(n个)
如果说n是4,那么sum=a+3b+3c+d。
如果说n是5,那么sum=a+4b+6c+4d+e。
{我看了题解才发现的问题,orz!原来是这样子。我们可以利用搜索对数字进行组合}
状态转移方程: C(r,n)=(n-r+1)*C(r,n-1)/r; 组合数
2.题解如下所示:(洛谷中借鉴的)
#include<iostream>
#include <cstdio>
#include <cstring>
#include <set>
using namespace std;
int ha[100],flag,yh[13][13];
bool v[100];
int n,sum;
void print() {
for(int i = 1;i <= n;i++)
printf("%d ",ha[i]);
}
void dfs(int step,int ans) {
if(ans>sum||flag) return ;
if(step==n+1&&ans==sum) {
print();
flag = 1;
return ;
}
for(int i = 1;i <= n;i++) {
if(!v[i]) {
ha[step] = i;
v[i] = 1;
dfs(step+1,ans+i*yh[n][step]);
v[i] = 0;
}
}
}
int main()
{
cin >> n >> sum;
yh[1][1] = 1;
for(int i = 2;i <= n;i++)
for(int j = 1;j <= i;j++)
yh[i][j] = yh[i-1][j-1] + yh[i-1][j];
dfs(1,0);
return 0;
}
简单粗暴的暴力搜索代码,可以把是个数据全部AC。
解释一下代码:
1.ha数组代表了记录数字的排列顺序
2.我们可以能简单地对第一个满足条件的数字组合进行输出,这就是字典序输出的最小值
3.ans+i*yh[n][step] 表示前i+1个数字的最大数值
4.在主函数里面,用两个for循环对yh进行一个杨辉三角的规律输入