今天我们聊聊组合数学。(本期是给刚刚学习组合数学的同学看的,dalao们可以自行忽略)
建议:不会求逆元的出门左转数论<2>,不会数论的出门右转数论<1>。
加乘原理
加乘原理小学奥数就有。
总的来说:加法原理:分类;乘法原理:分步
比如说,我问你有3条裤子2件衣服,只买一个,有几种可能性?3+2对吧。
那还是3条裤子2件衣服,每个买一个,有几种?3*2对吧。
排列组合
排列组合也是小学奥数的东西。
举个栗子,n个学生,选m个出来排队,有几种方案?!
稍微解释一下。
那还是刚刚的问题,但是不考虑排队的顺序,有几种方案?!
由于不考虑方案,所以要在的基础上除,也就是。
圆排列
有N个人围成一个圈,圈可以顺时针旋转,问有多少种方案?
其实很简单。不考虑圈是,考虑了是,也就是除掉一个N。
隔板法
原型:,问有多少种方案。
在旁边放隔板,有个隔板,所以答案是
变形1:,可以是,问方案数。
把每个加1,也就是。
答案是。
变形2:,求方案数。
,答案为!!!
变形3:,求方案数。
我们知道,,而每个的分解质因数都在里,就得到
,然后就转化为原型。(是每个数的指数)
-----------------------------------------↑数学-------↓实现-----------------------------------------
求组合数
首先可以想到的是根据定义操作。
int C(int n,int m){
int res=1;
for(int i=m-n+1;i<=m;i++)
res=res*i/(i-m+n);
return res;
}
我这里稍微优化了一下,边乘边除,防止溢出。
取模组合数
有的题ans太大了,需要大家取模。但是在数论<2>中我们说过,这除法有鬼啊,模不了,不能只
接求,那怎么办呢?
杨辉三角递推
观察杨辉三角,你会发现,杨辉三角的就是的值。(竖过来看)
而且,还满足,因此就可以求组合数了。
而且这是加法,很好模。当然,它只适用于和较小的情况。
逆元
或许大家有疑问,我们能不能搞个前缀积,然后
还搞什么杨辉三角呢?有道理,但是我们知道,除法并不支持模运算(⊙︿⊙)
所以,我们可以用逆元。逆元怎么求在数论<2>中说过,这里不再赘述。
然后,根据上面的式子就可以求逆元啦!
long long factorial[maxn],invf[maxn];
long long exgcd(long long a,long long b,long long &x,long long &y){
if(b==0){
x=1;
y=0;
return a;
}
long long res=exgcd(b,a%b,x,y);
long long tmp=x;
x=y;
y=tmp-a/b*y;
return res;
}
long long inverse(long long n,long long mod){
long long x,y;
long long _=exgcd(n,mod,x,y);
x%=mod;
if(x<0)
x+=mod;
return x;
}
void precompute(){
factorial[0]=1;
for(int i=1;i<=maxn;i++)
factorial[i]=factorial[i-1]*i%P;
invf[maxn]=inverse(factorial[maxn],P);
for(int i=maxn-1;i>=0;i--)
invf[i]=invf[i+1]*(i+1)%P;
}
long long C(int n,int m){
long long res=factorial[n];
res=res*invf[n-m]%P;
res=res*invf[m]%P;
return res;
}
都开了long long,因为组合数学题的范围一般很大。
例题
很easy,就搞定了。边乘边除即可。
CF1081C:
有n块砖,切k刀,即,由于颜色不确定,要再乘上
由于和较小,用杨辉三角求组合数即可。
CF630I:
很简单。答案是:。
CF1433E:
圆排列板题。答案是。
CF1236B:
答案是。
ok,以上就是本期的全部内容了,我们下期再见!_(:з」∠)_
小贴士:大部分组合数学题目不是板题,大家应该灵活一些,先分类,再分步,定序去重。
当然,你也可以每道题都用高精度。