5、不等式数列--百度2017春招

[编程题] 不等式数列

时间限制:1秒

空间限制:32768K

度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 ‘>‘ 和 ‘<‘ )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即(‘<‘‘)和n-k-1个大于符号(即‘>‘),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。

输入描述:

输入包括一行,包含两个整数n和k(k < n ≤ 1000)

输出描述:

输出满足条件的排列数,答案对2017取模。

输入例子:

5 2

输出例子:

66

解题思路:首先想到的是暴力的方式解决该问题

1)求出所有1-n的数的全排列分别存入vector中

2)对每一种排列,如果前一个小于后一个,小于数目--;如果大于则,大于数目--

3)如果一次操作过后,xiaoyu为0 && dayu为0  则符合条件,result++

4)输出result%2017

 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4
 5
 6 void swap(int* p1,int* p2)
 7 {
 8     int temp = *p1;
 9     *p1 = *p2;
10     *p2 = temp;
11 }
12 vector<vector<int> > res;
13 //获得1-n 全排列的个数,并存储全排列结果
14 void recall(int* arr,int len,int index,int *count)
15 {
16     vector<int> tmp;
17     if (index<=0)
18     {
19         (*count)++;//由于优先级的关系,记得加括号
20         for(int i=0;i<len;i++)
21         {
22             //cout<<arr[i]<<" ";
23             tmp.push_back(arr[i]);
24         }
25         res.push_back(tmp);
26         tmp.clear();
27         //cout<<endl;
28         return;
29     }
30     for (int i=index;i>=0;i--)
31     {
32         swap(&arr[index],&arr[i]);
33         recall(arr,len,index-1,count);
34         swap(&arr[index],&arr[i]);
35     }
36 }
37
38
39 int main()
40 {
41     int n;
42     int k;
43     while(cin>>n>>k)
44     {
45         int count = 0;
46         int result = 0;
47         int a[n];
48
49         for(int i=0;i<n;i++)
50         {
51             a[i] = i+1;
52         }
53         recall(a,n,n-1,&count);
54         //cout<<count<<endl;
55         for(int i=0;i<count;i++)
56         {
57             int xiaoyu = k;
58             int dayu = n - k - 1;
59             for(int j=0;j<n-1;j++)
60             {
61                 //cout<<res[i][j]<<"  ";
62                 if(res[i][j]< res[i][j+1])
63                 {
64                     xiaoyu--;
65                 }
66                 else if(res[i][j]>res[i][j+1])
67                 {
68                     dayu--;
69                 }
70             }
71             //cout<<endl;
72             //cout<<"k"<<xiaoyu<<"add"<<dayu<<endl;
73             if(xiaoyu==0 && dayu == 0)
74             {
75                 result++;
76             }
77         }
78         cout<<result%2017<<endl;
79     }
80     return 0;
81 }

正确解法:

递归公式:dp[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1)) % 2017;

dp[i][j]表示有i个数字及j个小于号所能组成的数量(大于号数量当然是i - j - 1次,后面需要使用)

而加入第i + 1个数字时,分以下四种情况:

1、如果将i+1插入当前序列的开头,即有了1<2,加入后成为3>1<2,会发现等于同时加入了一个大于号

2、如果将i+1插入当前序列末尾,即1<2变成了 1<2<3,会发现等于同时加入了一个小于号

3、如果将i+1加入一个小于号之间,即已经有 1<2了,向中间加入3,会发现变成了1<3>2,等于同时加入了一个大于号

4、如果将i+1加入一个大于号中间,即有了2>1,变成了2<3>1,等于同时加入了一个小于号

综上所述,dp[i][j]等于以上四种情况之和:

dp[i - 1][j]          //将i加在开头等于加入一个大于号,即要求i-1个数时已经有了j个小于号

dp[i - 1][j - 1]    //将i加在末尾等于加入一个小于号,即要求i-1个数时已经有了j-1个小于号

dp[i - 1][j] * j     //将i加在任意一个小于号之间,等于加入了一个大于号;即要求i-1个数时已经有了j个小于号,每个小于号都可以进行这样的一次插入

dp[i - 1][j - 1] * (i- j - 1)    //将i加在任意一个大于号之间,等于加入了一个小于号;即要求i-1个数时有了j-1个小于号,而此时共有(i - 1) - (j - 1)- 1个大于号,每个大于号都要进行一次这样的操作

合并同类项即为

dp[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1))

最后要记得取模。。。

初始化dp[i][0] = 1  因为全部为大于号时,只有一种排列方式

 1 #include <iostream>
 2
 3 using namespace std;
 4
 5 int main()
 6 {
 7     int dp[1005][1005];
 8     int n, k;
 9     while(cin>>n>>k)
10     {
11         for(int i = 1; i <= n; i++)
12         {
13             dp[i][0] = 1;
14         }
15         for(int i = 2; i <= n; i++)
16         {
17             for(int j = 1; j <= k; j++)
18             {
19                 dp[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1)) % 2017;
20             }
21         }
22         cout << dp[n][k] % 2017 << endl;
23     }
24     return 0;
25 }

时间: 2024-08-11 20:43:19

5、不等式数列--百度2017春招的相关文章

百度2017春招笔试真题编程题之有趣的排序

问题描述: 度度熊有一个N个数的数组,他想将数组从小到大 排好序,但是萌萌的度度熊只会下面这个操作: 任取数组中的一个数然后将它放置在数组的最后一个位置. 问最少操作多少次可以使得数组从小到大有序? 输入描述: 首先输入一个正整数N,接下来的一行输入N个整数.(N <= 50, 每个数的绝对值小于等于1000) 输出描述: 输出一个整数表示最少的操作次数. 示例1 输入 4 19 7 8 25 输出 2-----------------------------------------------

百度2017春招笔试真题编程题集合之寻找三角形

题目描述 三维空间中有N个点,每个点可能是三种颜色的其中之一,三种颜色分别是红绿蓝,分别用'R', 'G', 'B'表示. 现在要找出三个点,并组成一个三角形,使得这个三角形的面积最大.但是三角形必须满足:三个点的颜色要么全部相同,要么全部不同. 输入描述: 首先输入一个正整数N三维坐标系内的点的个数.(N <= 50) 接下来N行,每一行输入 c x y z,c为'R', 'G', 'B' 的其中一个.x,y,z是该点的坐标.(坐标均是0到999之间的整数) 输出描述: 输出一个数表示最大的三

网易2017春招笔试真题编程题集合题解

01 双核处理 题目 一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务.n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间. 输入描述 输入包括两行:第一行为整数n(1 ≤ n ≤ 50)第二行为n个整数lengthi,表示每个任务的长度为length[i]kb,每个数均为1024的倍数. 输出描述输出一个整数,表示最少需

(百度17春招笔试题)有趣的排序

时间限制:1秒 空间限制:32768K 度度熊有一个N个数的数组,他想将数组从小到大 排好序,但是萌萌的度度熊只会下面这个操作:任取数组中的一个数然后将它放置在数组的最后一个位置.问最少操作多少次可以使得数组从小到大有序? 输入描述: 首先输入一个正整数N,接下来的一行输入N个整数.(N <= 50, 每个数的绝对值小于等于1000) 输出描述: 输出一个整数表示最少的操作次数. 输入例子: 4 19 7 8 25 输出例子: 2 思路:找到数组中的乱序的个数就行.比如:数列5 1 4 2 3,

蘑菇街2017春招笔试

现在有一个n个证书的序列,交换两个相邻的数的位置直到整个序列按照升序排列, 那么将整个序列排好需要交换多少次? 例如 1,2,3,5,4 只需要交换一次即可. 第一行输入一个正整数n(n<100),表述数字序列元素个数,占一行: 接下来一行输入从1到n的n个整数序列,中间用空格隔开 输入: 4 4 3 2 1输出: 6 1 /************************************************************************* 2 > File Na

(百度17春招笔试题) 度度熊回家

时间限制:1秒 空间限制:32768K 一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家.现在他需要依次的从0号坐标走到N-1号坐标.但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个点,并直接将这个点忽略掉,问度度熊回家至少走多少距离? 输入描述: 输入一个正整数N, N <= 50. 接下来N个整数表示坐标,正数表示X轴的正方向,负数表示X轴的负方向.绝对值小于等于100 输出描述: 输出一个整数表示度度熊最少需要走的距离. 输入例子: 4 1

去哪儿网2017春招在线笔试

第一题,给二叉树的先序遍历和中序遍历,求层序遍历. 这个...大二做的... 根据先序和中序的性质,先序第一个节点一定是根,在中序中找到根的位置,左边的就是左子树,右边的就是右子树,递归就好. 递归建好树  层先遍历需要通过队列实现. #include <bits/stdc++.h> using namespace std; struct bi_tree { int val; bi_tree *left, *right; }; bi_tree *build_tree(int a[], int

网易2017春招笔试真题编程题集合(8)——奇怪的表达式求值

常规的表达式求值,我们都会根据计算的优先级来计算.比如*/的优先级就高于+-.但是小易所生活的世界的表达式规则很简单,从左往右依次计算即可,而且小易所在的世界没有除法,意味着表达式中没有/,只有(+, - 和 *).现在给出一个表达式,需要你帮忙计算出小易所在的世界这个表达式的值为多少 输入描述: 输入为一行字符串,即一个表达式.其中运算符只有-,+,*.参与计算的数字只有0~9. 保证表达式都是合法的,排列规则如样例所示. 输出描述: 输出一个数,即表达式的值 输入例子: 3+5*7 输出例子

网易2017春招笔试真题编程题集合(7)——集合

小易最近在数学课上学习到了集合的概念,集合有三个特征:1.确定性 2.互异性 3.无序性.小易的老师给了小易这样一个集合:S = { p/q | w ≤ p ≤ x, y ≤ q ≤ z }需要根据给定的w,x,y,z,求出集合中一共有多少个元素.小易才学习了集合还解决不了这个复杂的问题,需要你来帮助他. 输入描述: 输入包括一行: 一共4个整数分别是w(1 ≤ w ≤ x),x(1 ≤ x ≤ 100),y(1 ≤ y ≤ z),z(1 ≤ z ≤ 100).以空格分隔 输出描述: 输出集合中