\(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}\)
- 总结心得
-
组合数针对的是集合,他是无序的,当像本题一样针对某一种选法排列数是唯一的时候,可以利用组合数的无序性进行求解
-
组合数的根本是加法原理与乘法原理,理科的东西一定要回到根本上去。
#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;
}