组合数的题型

标准的C(n,m)求解

  • 包括输出所有组合数
#if 0

// 对于求C(n, m),从第一个字符开始扫描,每个字符有两种情况,要么被选中,要么不被选中,如果被选中,递归求解C(n-1, m-1)。
// 如果未被选中,递归求解C(n-1, m)。不管哪种方式,n的值都会减少,递归的终止条件n=0或m=0。

// 数组的全组合数
void combination(vector<int> src, int i,int m, vector<int> &res, vector<vector<int>> &vecs)
{
    if (i>=src.size()&&m!=0)
    {
        return;
    }
    if (m==0) //递归终止条件
    {
        copy(res.begin(), res.end(), ostream_iterator<int>(cout, " "));
        cout << endl;
        return;
    }  
    //选择该元素
    res.push_back(src[i]);
    combination(src, i + 1, m - 1, res, vecs);
    res.pop_back();
    //不选该元素
    combination(src, i+1, m, res, vecs);

    return;
}

int main()
{

    int m, n;
    cin >> m >> n; //C(n,m)
    vector<int> input;
    for (int i = 0; i < n;i++)
    {
        input.push_back(i + 1);
    }

    vector<vector<int>> vecs;
    vector<int> vec;
    //combination(input,0, m, vec, vecs); C(n,m)


    for (int i = 1; i <= n;i++) //C(n, 1), C(n, 2),...C(n, n)的总和
    {
        combination(input,0,i,vec,vecs); C(n,m)
    }

    return 0;
}


#endif
  • 结果

864046-20180329143937077-249337035.png

题目

链接:https://www.nowcoder.com/questionTerminal/dd7fe2adc9ec4da5a91da1e224a7ad55
来源:牛客网

科室素拓进行游戏,游戏规则如下:随机抽取9个人作为游戏参与人员,分别编号1至9,每轮要求k(k<=9且k>=0)个人自由组合使编号之和为n。输出满足规则的所有可能的组合。要求组合内部编号升序输出,组合之间无顺序要求。
输入描述:

输入数据为以空格分隔的两个整数k和n



输出描述:

每行输出一个可能的编号组合,组合内部各个编号以空格分隔升序输出。若无满足规则的组合,则输出None

示例1
输入

3 15

输出

1 5 9
1 6 8
2 4 9
2 5 8
2 6 7
3 4 8
3 5 7
4 5 6

解析

#include<iostream>
#include<math.h>

#include <vector>
#include <string>
#include <deque>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>

#include <algorithm>
#include <functional>
#include <numeric> //accmulate

#include <iterator> //ostream_iterator
#include <fstream>
#include <iomanip>  //setprecision() setw()
using namespace std;

//#define cin infile //一定不能再oj系统中,有错,导致超时等!!!
//C++文件输入
ifstream infile("in.txt", ifstream::in);  

#include <limits>
#define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
#define INT_MAX       2147483647    /* maximum (signed) int value */


#if 1

bool flag = false;

void combination(vector<int> src, int i, int m, vector<int> &res, vector<vector<int>> &vecs,int target)
{
    if (i >= src.size() && m != 0)
    {
        return;
    }
    if (m == 0) //递归终止条件,个数
    {
        if (accumulate(res.begin(), res.end(), 0) == target)
        {
            flag = true;
            copy(res.begin(), res.end(), ostream_iterator<int>(cout, " "));
            cout << endl;
        }
        return;
    }
    //选择该元素
    res.push_back(src[i]);
    combination(src, i + 1, m - 1, res, vecs,target);
    res.pop_back();
    //不选该元素
    combination(src, i + 1, m, res, vecs,target);

    return;
}

int main()
{
    int a[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    int m, n;
    cin >> m >> n; //C(9,m) ;sum()=n
    vector<int> input(a,a+9);
    
    vector<vector<int>> vecs;
    vector<int> vec;
    combination(input, 0, m, vec, vecs,n); C(n,m)

    if (!flag)
    {
        cout << "None" << endl;
    }

    return 0;
}


#endif
#if 1

void PrintCombination(int *a, int n, int sum, vector<int>& vec)
{   //a为输入数组,n为数组长度,sum为待查找的和,vec用于保存查找到的组合
    if (sum==0)
    {
        vector<int>::iterator iter=vec.begin();
        for (;iter!=vec.end();iter++)
        {
            cout<<*iter<<" ";
        }
        cout<<endl;
        return;
    }
    else if(sum<0 || n<=0)
        return;
    vec.push_back(a[0]);//a[0]即*a,注指针a是变化的,每次指向后一个
    PrintCombination(a+1,n-1,sum-a[0],vec);
    vec.pop_back();

    while(*a == *(a+1) && a < a+n) //跳过重复的数字  
        a++; 
    PrintCombination(a+1,n-1,sum,vec);
}

void main()
{
    int a[8]={8,3,6,5,7,2,4,1};
    cout<<"原来的数组:";
    copy(a, a + 8, ostream_iterator<int>(cout, " "));

    sort(a,a+8);
    cout<<"排序后数组:";
    copy(a, a + 8, ostream_iterator<int>(cout, " "));
    cout<<"-----------------------------"<<endl;

    vector<int> vec;
    int sum=10;
    cout<<"和为"<<sum<<"的组合如下:"<<endl;
    PrintCombination(a,8,sum,vec);

    return;
}


#endif

864046-20180329151005803-303416686.png

问题2:求从n个数组任意选取一个元素的所有组合

求从n个数组任意选取一个元素的所有组合,对于这个问题,我们在直观上感觉很容易,但是用程序实现时则发现用for循环解决不了问题,因为n是随意的。
在这里,我们用递归的思想,对于数据[1, 3, 4]; [2, 5]; [6, 7];

问题3:打靶问题。一个射击运动员打靶,靶一共有10环,连开10 枪打中90环的可能性有多少?

  • 思路:这道题的思路与字符串的组合很像,用递归解决。一次射击有11种可能,命中1环至10环,或脱靶。
  • 参考代码
//函数功能 : 求解number次打中sum环的种数  
//函数参数 : number为打靶次数,sum为需要命中的环数,result用来保存中间结果,total记录种数   
//返回值 :   无  
void ShootProblem_Solution1(int number, int sum, vector<int> &result, int *total)  
{  
    if(sum < 0 || number * 10 < sum) //加number * 10 < sum非常重要,它可以减少大量的递归,类似剪枝操作  
        return;  
    if(number == 1) //最后一枪  
    {  
        if(sum <= 10) //如果剩余环数小于10,只要最后一枪打sum环就可以了  
        {  
            for(unsigned i = 0; i < result.size(); i++)  
                cout<<result[i]<<' ';  
            cout<<sum<<endl;  
            (*total)++;  
            return;  
        }  
        else  
            return;  
    }  
    for(unsigned i = 0; i <= 10; i++) //命中0-10环  
    {  
        result.push_back(i);  
        ShootProblem_Solution1(number-1, sum-i, result, total); //针对剩余环数递归求解  
        result.pop_back();  
    }  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
概率论与数理统计是数学中非常重要的一门学科,它研究的是随机事件的发生规律以及通过概率的方法对随机数据进行统计分析。 在概率论的题型中,常见的有求解概率的问题,如求事件发生的概率、条件概率以及多次试验后的概率等。例如,某班级中有男生40人,女生60人,现从班级中随机抽取一人,求抽到男生的概率。解决这个问题可以先计算男生的人数与总人数的比例,即40/100=0.4,所以抽到男生的概率为0.4。 另外还有排列组合的问题,如从一副扑克牌中随机抽取5张牌,求出现顺子的概率。解决这个问题需要先计算出一副扑克牌中顺子的可能情况共有多少种,再除以总的可能情况。 数理统计题型主要包括参数估计和假设检验。在参数估计方面,常见的题目是根据样本数据估计总体参数的值。例如,从某个城市随机抽取1000名居民的身高数据,根据这个样本数据计算出城市居民的平均身高。在假设检验方面,常见的题目是根据给定的样本数据判断关于总体参数的假设是否成立。例如,某种电子产品的平均使用寿命宣称为10000小时,现在通过抽取一批产品进行测试,测试结果显示平均使用寿命为9500小时,需进行假设检验来判断该产品的平均使用寿命是否满足宣称值。 总之,概率论与数理统计题型很多,但核心思想是通过概率的计算和统计方法来揭示随机事件的规律以及对随机数据进行准确的分析和判断。这些题目的解答需要运用概率论和数理统计的相关理论和方法,进行具体的计算和推理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值