我又来颓文化啦!
题目描述
从 n n n个空位中选择一些空位种 m m m樱花,要求每两棵樱花之间至少要有一个空位.
求合法种植数.
题目分析
这不是五三水题嘛。。。
首先,看到这种“一个空位”的问题,第一想法就是把一棵樱花和它后面的空位视为一组(或者一个数).
另外我们可以发现,如果最后一个元素在n位置上时,那么是不用考虑它后面的那个空位的.
所以思路就出来了:分类讨论.
第一,如果最后一个元素不在 n n n位置上,那么此时相当于有 n − m n-m n−m个空位,要插入 m m m个元素,再加上这 m m m个元素自身的排列,总共有 A m m C n − m m A_{m}^{m}C_{n-m}^{m} AmmCn−mm种合法方案.
第二,如果最后一个元素在 n n n位置上,那么此时相当于有 ( n − 1 ) − ( m − 1 ) = n − m (n-1)-(m-1)=n-m (n−1)−(m−1)=n−m个空位,要插入 m − 1 m-1 m−1个元素,同样加上他们自身的排列,总共有 A m m C n − m m − 1 A_{m}^{m}C_{n-m}^{m-1} AmmCn−mm−1种方案.
另外, A m m C n − m m − 1 = m ∗ A n − m m − 1 A_{m}^{m}C_{n-m}^{m-1}=m*A_{n-m}^{m-1} AmmCn−mm−1=m∗An−mm−1, A m m C n − m m = A n − m m A_{m}^{m}C_{n-m}^{m}=A_{n-m}^{m} AmmCn−mm=An−mm,我们直接处理排列数即可.
求和,而我们知道 A x y + y ∗ A x y − 1 = A x + 1 y A_{x}^{y}+y*A_{x}^{y-1}=A_{x+1}^{y} Axy+y∗Axy−1=Ax+1y,这样就可以一遍用 O ( n ) O(n) O(n)求得最后的值.
问我算法?不就是某位老师在视频里说的吗?从中间某位开始算啊!
#include<bits/stdc++.h>
#define ll long long//防止计算时溢出
using namespace std;
ll type,n,m,mod,ans=1;
int main(){
scanf("%lld%lld%lld%lld",&type,&n,&m,&mod);
for(ll i=n-2*m+2;i<=n-m+1;i++){
ans=(ans*i)%mod;
}
printf("%lld\n",ans);
return 0;
}
题后反思
尽量把组合数化简到最简的形式,最好是一遍 O ( n ) O(n) O(n)就可以算出来的一维组合数/排列数形式.
注意利用各个公式进行灵活的转换.