\(C_n^m=\frac{n!}{m!(n-m)!}\)

  • 此篇文章主要处理组合数的一些习题和一些组合数思想

例题 1.P3197 【HNOI2008】越狱

  • 题目翻译(做题即翻译!)

\(n\) 个球,\(m\) 个盒子,盒子可以为空,问有多少种情况相邻的两个球在一个盒子里。

  • 题解

考虑所有情况,就等价于 n 个氨基酸形成一条 m 肽,答案是 \(m^n\)

现在要减去不合理的情况。

组合数学的问题都是从两个基本原理出发的,这里用的就是乘法原理,乘法原理的意识要有。

只考虑第一个球,他有 \(m\) 种状态可以选择,然而第二个球就只能选择 \(m-1\) 种状态,后面的就都是 \(m-1\) 种状态。

所以 \(ans=n^m-(n-1)^{m-1}* m\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
#define ll long long
using namespace std;
const int P = 100003;
int n,m;
int power(int a,int b){
	if(!b)return 1;
	int k=power(a,b/2);
	k=(ll)k*k%P;
	if(b&1)k=(ll)k*a%P;
	return k;
}
signed main(){
	scanf("%lld%lld",&m,&n);
	ll ans=(power(m,n)-power(m-1,n-1)*m%P)+P%P;
	printf("%lld",(ans+P)%P);
	return 0;
}

例 2. 【石家庄二中集团20210220模拟赛】div.2 T2 伞坊

本题来自 \(zky\) 学长

  • 题目翻译

给你一种具有唯一性质的数列,要求求出满足这种排列的数列的个数。

具体题意自己看 pdf 吧 qwq

  • 题解

对于高度为 \(m\) 的这把伞,已经是确定了的,我们不在管他。

剩下的 \(m-1\)个伞的高度还未确定,如果 \(m\) 的位置是确定的话,那么肯定有 \(C_{n-1}^{m-1}\) 种可能。

然而 \(m\) 的位置并不是确定的。

那么问题等价于对于这 \(m-1\) 个数,他们既可以放到 \(m\) 的左边,又可以放到右边

这样我们就把 \(m\) 位置的变化转化为了一个组合数的问题。

这下面就类似于 例 1,现在有 \(m-1\) 个球,有 \(2\) 个盒子,盒子可以为空,则方案数为 \(2^{n-1}\)

利用乘法原理\(ans=C_{m-1}^{n-1}*2^{n-1}\)

  • 总结心得
  1. 组合数针对的是集合,他是无序的,当像本题一样针对某一种选法排列数是唯一的时候,可以利用组合数的无序性进行求解

  2. 组合数的根本是加法原理与乘法原理,理科的东西一定要回到根本上去。

#include<bits/stdc++.h>
using namespace std;

#define int long long

const int mod=998244353;
const int N=200005;

int fpow(int x,int y){
	int ans=1;
	while(y){
		if(y&1)ans=ans*x%mod;
		x=x*x%mod;
		y>>=1;
	}
	return ans%mod;
}

int fac[N],inv[N];

int c(int x,int y){
	return fac[x]*inv[y]%mod*inv[x-y]%mod;
}

int n,m;

signed main(){
	cin>>n>>m;
	if(m<n){
		cout<<0;
		return 0;
	}
	fac[0]=1;
	for(int i=1;i<=m;i++){
		fac[i]=fac[i-1]*i%mod;
	}
	inv[m]=fpow(fac[m],mod-2);
	for(int i=m;i>=1;i--){
		inv[i-1]=inv[i]*i%mod;
	}
	cout<<(c(m-1,n-1)%mod*fpow(2,n-1)%mod);
	return 0;
}