排列组合简单练习

本文探讨了组合数学在解决实际问题中的应用,包括排列组合的基本概念及其在摄影排列、字符串构造和水果分配问题中的具体运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

照相

题目描述

某个班级有N个学生,现在从中选择r个学生出来,从左往右排成一行照相,有多少种不同的排列?答案模10007.

输入格式

一行,N和r。1 <= N<=1000, 1<=r<=N

输出格式

一个整数。

输入样例
1000  2
输出样例
8307

解题思路

本题分两步走:

  1. 选出这r个学生:CNrC{^r_N}CNr
  2. 排列这r个学生:ArrA{^r_r}Arr
    因为是分步执行,所以是乘法原理CNr×ArrC{^r_N}\times A{^r_r}CNr×Arr

代码

#include<iostream>
#include<fstream>

using namespace std;
int N,r;
unsigned long long p=1,ans=1,f[1005][1005];

int main()
{
	freopen("1034.in","r",stdin);
	freopen("1034.out","w",stdout);
	cin>>N>>r;
	for(int i=1;i<=r;i++)
	{
		p*=i;
		p%=10007;
	}
	for(int i=0;i<=N;i++)
	{
		f[i][i]=1;
		f[i][0]=1;
	}
	for(int i=1;i<=N;i++)
		for(int j=1;j<i;j++)
		{
			f[i][j]=f[i-1][j]+f[i-1][j-1];
			f[i][j]%=10007;
		}
	ans=f[N][r]*p%10007;
	cout<<ans;
	return 0;
}


L字符串

题目描述

由小写字母构成的长度是L的字符串,要求相邻的字符不相同,问这样的字符串总共有多少个?答案模10007。

输入格式

一个整数L 。 1 <= L <= 100.

输出格式

一个整数。

输入样例
2
输出样例
650

解题思路

我们单独考虑每一个位置的情况:
第一个位置26个字母可以任意放置,第二个位置不能与第一个位置相同,所以可以放25个字母,第三个位置不能与第二个位置相同,所以可以放25个字母,为什么第三个位置可以放25个字母呢?我们看看以下序列:

位置123
放置了的字母ab?

前面两个位置是合法的,我们来思考一下第三个位置,因为题目说不与相邻的字母相同,所以第三个位置可填:
a,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
一共25个字母。同理,后面的位置也可填25个字母,由此可以列出以下表格:

位置123⋯\cdotsL−1L-1L1
可放置的字母方案数262525⋯\cdots25

答案就是:26×25L−126\times 25{^{L-1}}26×25L1


代码

#include<iostream>
#include<fstream>

using namespace std;
int L;
int ans=26;
int main()
{
	freopen("1036.in","r",stdin);
	freopen("1036.out","w",stdout);
	cin>>L;
	/*
	第一个位置可以填26个字母 
	因为题目要求相邻的字符不相同,所以第二个位置可以填25个字母,不能与第一个相同 
	第三个位置也可以填25个字母,不会与第二个位置字母相同
	以此类推: 
				1 	 2 	  3 	...	   L-1 	 L
	answer =	26 * 25 * 25  * ...  * 25  * 25
	*/
	for(int i=1;i<L;i++)
	{
		ans*=25;
		ans%=10007;
	}
	cout<<ans;
	return 0;
}


派水果

题目描述

若一位母亲手里有m个相同的苹果,还有n个相同的梨,在m+n天内分给她的小孩,每天分一个水果,有多少种不同的分派方案?答案模10007。

输入格式

一行,m和n, 1 <= m,n <= 1000。

输出格式

一个整数。

输入样例
2 3
输出样例
10

解题思路

(本题思路作者不是很记得了,所以解释的会略有含糊,还请望各位大佬给出一种十分明确的解释)
从题目可以得知,有mmm相同的苹果,还有nnn相同的梨,那么就不属于排列问题了,而是一个组合问题。

在这m+nm+nm+n天里,怎么组合这mmm个苹果和nnn个梨呢?
通过手动模拟样例,我们可以发现,只要求出m+nm+nm+nmmmnnn中最小的一个数的组合数就可以得到正解了。
因为如果用较大的一个数做计算,会出现一些虽然分配顺序不同,但分配方案相同的情况,不符合题意。
所以本题正解:Cm+nmin(m,n)C{_{m+n}^{min(m,n)}}Cm+nmin(m,n)


代码

#include<iostream>
#include<fstream>

using namespace std;
int n,m;
int f[3005][3005];

int main()
{
	freopen("1035.in","r",stdin);
	freopen("1035.out","w",stdout);
	cin>>m>>n;
	for(int i=0;i<=m+n;i++)
	{
		f[i][i]=1;
		f[i][0]=1;
	}
	for(int i=1;i<=m+n;i++)
	{
		for(int j=1;j<i;j++)
		{
			f[i][j]=f[i-1][j]+f[i-1][j-1];
			f[i][j]%=10007;
		}
	}
	cout<<f[m+n][min(m,n)]%10007;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值