问题是求n个不同座位围成一个圆,m个孩子至少间隔k个座位坐,一共有多少种方法。
首先,第一个孩子做,有n种方法。
第一个孩子坐下后,剩下的能够坐的座位有n-1-k*m,将间隔的椅子拿走
剩下的m-1个孩子们一共还有,又因为这是一个圆排列,所以要除以孩子的总数m,最终的结果为种方法。
上面仔细思考是用意确定的,接下来是题目的关键,大组合数取模
第一种,利用逆元:因为mod=1e9+7是一个素数,所以有:
利用快速幂即可
AC代码:
/*************************************************************************
> File Name: HDU5984(2).CPP
> Author:Xingxing
> Created Time: 2016/9/22 0:22:34
************************************************************************/
#include <cstdio>
#include<iostream>
typedef long long ll;
const int mod=1e9+7;
using namespace std;
ll n,m,k;
ll quickpow(ll a,ll b){
ll p=1;
while(b>0){
if(b&1)
p=p*a%mod;
b=b>>1;
a=(a%mod)*(a%mod)%mod;
}
return p;
}
ll C(int n,int m){
if(n<m)
return 0;
ll ans=1;
for(int i=1;i<=m;i++){
//cout<<ans<<endl;
ans=ans*((n-m+i)*quickpow(i,mod-2)%mod)%mod;
}
return ans;
}
int main()
{
freopen("input.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
scanf("%lld%lld%lld",&n,&m,&k);
ll res;
if(m==1) //m=1需要特判
res=n;
else{
res=((n*C(n-1-k*m,m-1))%mod*(quickpow(m,mod-2)%mod))%mod;
}
printf("%lld\n",res);
}
}
我再这个位置调试了2个小时,好气哦
ans=ans*((n-m+i)*(quickpow(i,mod-2)%mod))%mod;
ans=ans*((n+i-m)*quickpow(i,mod-2)%mod)%mod;
下面的是正确的
第二中,套路Lucas公式,具体的我也不做介绍了,找了一个模版,交了一发
AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const int maxn=1e6+10;
const LL mod=1e9+7;
LL n,m,k;
LL fac[maxn],inver[maxn];
LL quickpow(LL a,LL b,LL c){
LL res=1;
while(b>0){
if(b&1)
res=res*a%c;
b=b>>1;
a=(a%c)*(a%c)%c;
}
return res;
}
LL inv(LL a){ //求逆元
return quickpow(a,mod-2,mod);
}
void init()
{
fac[0]=1,fac[1]=1;
inver[0]=1,inver[1]=1;
for(int i=2;i<=maxn-10;i++)
fac[i]=fac[i-1]*i%mod,inver[i]=inver[i-1]*inv(i)%mod;
//for(int i=2;i<=maxn-10;i++)
// cout<<fac[i]<<endl;
}
LL C(LL a,LL b)
{
if(b>a)
return 0;
LL temp=fac[a]*inver[b]%mod*inver[a-b]%mod;
return temp;
}
LL lucas(LL a,LL b)
{
if(b==0)
return 1;
return C(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
}
int main()
{
//freopen("input.txt","r",stdin);
int T;
scanf("%d",&T);
init();
while(T--){
scanf("%lld%lld%lld",&n,&m,&k);
if(m==1){
printf("%lld\n",n);
continue;
}
else{
//cout<<lucas(n-k*m,m-1)<<endl;
LL ans=lucas(n-k*m-1,m-1)*n%mod*inv(m)%mod;
printf("%lld\n",ans);
}
}
return 0;
}