参考:
组合数学--不相邻的组合数_MatstanLy_的博客-CSDN博客blog.csdn.net一、从n个球中选出r个球,要求这r个球互不相邻,有多少种取法?
分析:①当n<2r-1时,取法为0种
例如4个球里取3个互不相邻的球,找不到这样的组合②n≥2r-1时,取法为C(n-r+1,r)种
这里考虑逆向思维。假设我们先从n-r+1个球中任意取r个球,组合数为C(n-r+1,r),然后再另外拿r-1个球插到那r个球的r-1个空位中,这样使得我们原本取出的r个球都互不相邻,并且最后总球数为n个。不难验证逆向思维得出的情况与正常考虑的情况是一一对应的,故我们可以得到上面的结论。
(临界情况:n=2r-1时,比如5个里取3个,7个里取4个,此时恰好只有C(n-r+1,r)=C(r,r)=1种取法)
二、从围成一圈的n个球中选出互不相邻的r个球有多少种不同的选法?
分析:①当n<2r时,取法为0种
例如4个球围一圈,选互不相邻的3个球,找不到这样的组合①当n>=2r时,取法为C(n-r,r)n/(n-r)种
首先对球进行编号,1号~n号,对于任何可能的组合,都只有两种情况:包含1号球的和不包含1号球的。
r个球包含1号球:首先选出1号球,然后需要从3号球~n-1号球取出r-1个互不相邻的球,根据上面那道题的结论,我们可以得到组合数为C(n-3-(r-1)+1,r-1)=C(n-r-1,r-1);
r个球里不包含1号球:我们需要从2号球~n号球取出r个互不相邻的球,其组合数为C(n-1-r+1,r)=C(n-r,r)
综上,总数为C(n-r-1,r-1)+C(n-r,r)=C(n-r,r)n/(n-r)
(临界情况:当n=2r时,例如4个取2个,6个取3个,共有C(r,r)*2r/r=2种)
(r/(n-r)) * C(n-r-1,r-1)= C(n-r,r)
题目:
餐厅里有一张圆形的桌子,桌子上有n个座位,座位按照顺序从1到n编号,而且n号座位和1号座位相邻,每个座位都不一样。m个人一起去这家餐厅吃饭。为了更好地就餐,他们不想坐得太过拥挤,因此,不允许有任意两个人相邻。
你知道一共有多少种不同的就坐方法吗?最后答案可能非常大,输出答案除以1000000007之后的余数。两种坐法不一样当且仅当存在一个人,在两种坐法中他坐在了不同的位置上。
输入:第一行一个数字T(T<=10)表示测试数据的组数。对于每组测试数据,输入两个数n和m(1<=n,m<=100000)。
4
3 1
3 2
4 2
50 10
输出: 每组数据输出一行,就坐的方案数,如果不存在合法的就坐方案,方案数为0。
3
0
4
128093084
思路:
第二种情况的全排列。
C(n-r,r)*(n/(n-r))*r! = n*[n-(r+1)]!/[n-2*r]!
#include<bits/stdc++.h>
using namespace std;
int main(){
int T;cin>>T;
while(T--){
int n,m; cin>>n>>m;
if(n<2*m){
int tmp=0; cout<<tmp<<endl;
}
else{
long long ans=n;
for(int i=m+1; i<=2*m-1; i++)
ans=ans*(n-i)%1000000007;
cout<<ans<<endl;
}
}
return 0;
}