算法期末函数题

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个数,为a1​a2​…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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值