R6-1 可重复选择的组合数问题
【考核知识点】可重复选择的组合计数
【问题描述】
有n个不同元素(1<=n<20),每个元素可以选多次,一共需要选出k个元素出来(1<=k<20),问有多少种选取的方法数?
例如,n=3,k=2,可以想象成有3种颜色的球(红、黄、蓝),选出2个来,有如下组合。
(红、红)
(红、黄)
(红、蓝)
(黄、黄)
(黄、蓝)
(蓝、蓝)
组合数共计:6种
再例如,n=2,k=6,可以想象成有2种颜色的球(红、黄),选出6个来,有如下组合。
(6*红)
(1*黄、5*红)
(2*黄、4*红)
(3*黄、3*红)
(4*黄、2*红)
(5*黄、1*红)
(6*黄)
组合数共计:7种
【输入格式】
n和k。n和k的含义如前述。
【输出格式】
从n种元素中,可重复选择挑选k个的组合数。
【提示】
从n种元素中,可重复选择挑选k个的组合数。假设第i 种元素选xi个,则此问题转化为求方程:
x1+x2+…+xn=k 的非负整数解的个数,xi 可以取0。这个方程由于求解非负整数解(xi可为0),不易分析,可以转化为:yi=xi+1,则求解 y1+y2+…+yn=k+n 的正整数解的个数(yi 不可为0,需要大于0)。
求解 y1+y2+…+yn=k+n 的正整数解的个数,可以想象成这样一个场景的问题:
有k+n个数字1,排成一排,则问题等价于把这些“1”分成n个部分,有多少种方法?这就相当于在k+n−1个“候选分隔线”(即1和1之间的空档)中选出n−1个空档的方法数。即C(k+n−1,n−1),也是C(k+n−1,k),因为C(k+n−1,n−1)=C(k+n−1,k)。
函数接口定义:
函数接口定义: long long Combination(int n, int k)
接口参数: n
和 k
都是传入的参数。 n
和k
的值都不超过20
,返回值为long long型,表示从n
个中选择k
个的组合数(不讲顺序)。
测试程序样例:
#include "stdio.h" #include <iostream> #include "stdlib.h" using namespace std; long long permutation(int n, int k); //计算A(n,k),n个中选k个的排列数 long long Combination(int n, int k); //计算C(n,k),n个中选k个的组合数 int main() { int n, k; cin >> n >> k; long long p; //其实,求解C(k+n-1,k)和C(k+n-1,n-1)是相同的,哪个好算算哪个 if(n-1>k) p=Combination(k+n-1,k); else p=Combination(k+n-1,n-1); cout<< p <<endl; return 0; } long long permutation(int n, int k) //计算A(n,k),n个中选k个的排列数 { long long p=1; for(int i=n; i>=n-k+1; i--) p *= i; return p; } /* 请在这里填写答案 */
输入样例#1:
在这里给出一组输入。例如:
3 2
输出样例#1:
在这里给出相应的输出。例如:
6
输入样例#2:
在这里给出一组输入。例如:
2 6
输出样例#2:
在这里给出相应的输出。例如:
7
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
C++ (g++)
long long Combination(int n, int k) {if (k > n) return 0; if (k == 0 || k == n) return 1; k = std::min(k, n - k); long long result = 1;for (int i = 1; i <= k; ++i) {result *= n - (k - i);result /= i;}return result;
}
R6-2 最大连续和
【考察知识点】前缀和、暴力法、分治法、动态规划等,多种方法皆可。
【问题描述】
给一个长度为n的序列a1,a2,…,an, 每个元素ai(1<=i<=n),为可正可负可零的整数。
求一个连续子序列ai,ai+1,…,aj,1<=i<=j<=n ,使得连续元素段的和ai+ai+1+…+aj最大。
【输入格式】
第一行n,表示序列的长度,n<100000。
第二行有n个数,为a1a2…an。
【输出格式】
最大的连续元素段之和,即 max{ai+ai+1+…+aj},1<=i<=j<=n 。
【函数接口定义】
函数接口如下: int maxSum(int a[], int n);
【裁判测试程序】
#include "stdio.h" #include <iostream> #include "stdlib.h" using namespace std; int maxSum(int a[], int n); int main() { int n, a[100000]; cin>>n; if(n>0) { for(int i=1;i<=n;i++) cin>>a[i]; } else return 1; int mxs=maxSum(a, n); cout<<mxs<<endl; return 0; } /* 请在这里填写答案 */
【输入样例】
在这里给出一组输入。例如:
10
-2 3 -3 2 4 8 6 1 -2 -4
【输出样例】
在这里给出相应的输出。例如:
21
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
#include <climits> int maxSum(int a[], int n) {int maxSoFar = INT_MIN; int maxEndingHere = 0; for (int i = 0; i < n; i++) {maxEndingHere += a[i];if (maxSoFar < maxEndingHere)maxSoFar = maxEndingHere;if (maxEndingHere < 0)maxEndingHere = 0;}return maxSoFar;
}