题目
题意:
现在 m个考生人需要坐在有n个座位的圆桌上。你需要安排位置,使得任意两个考生之间相距至少k个位置。桌子有编号,考生a和b交换位置视作一种方案,问有多少方案,mod 1e9+7。(0 < m < n < 1e6, 0 < k < 1000)
解法:
首先必须有n>=m+k*m,否则答案是0。
现在先考虑m个人的相对关系(即不考虑座位编号和人对应,先只考虑人与人间的间隔,即位置分配),
先在n个座位中抽走k*m个,每个人和k个座位绑在一起,一旦这个人有了座位,他后面自动添加这k个座位。
现在因为是确定相对关系,那么第一个人必有一个座位,那么剩下n-1-k*m个座位,在这之中选m-1个作为给其余人座,即C(n-1-k*m,m-1),现在相对位置就形成了。下面开始对号入座。
由于这第一个人有n中选择,选择[1,n]这n个座位编号,所以将答案先乘以n,即n*C(n-1-k*m,m-1)。不过这样做绝对比真实答案要大,因为是个环形,如果第一个人坐到靠后的位置,那么后面的人就会坐到编号较小的位置,所以就算的有重复,因为当初相对位置为第一的人实际不是总是对应最小编号。
想想 ,已经计算中的所有方法中,相对位置中的每个人实际成为其座位编号最小的人的机会是相等的,故将答案除以m,即n*C(n-1-k*m,m-1)/m。
另 :对于m=1,特判,因为1个人没有间隔。
代码:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s) memset(a,x,(s)*sizeof a[0])
#define mem(a,x) memset(a,x,sizeof a)
#define ysk(x) (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=1e6+0.5;
ll n,m,K,S[maxn+5];
ll inv(ll a,ll m)
{
if(a == 1) return 1;
return inv(m%a,m)*(m-m/a)%m;
}
void pre()
{
S[0]=1;
for1(i,maxn)
{
S[i]=S[i-1]*i%mod;
}
}
int main()
{
std::ios::sync_with_stdio(false);
pre();
int T;cin>>T;
while(T--)
{
cin>>n>>m>>K;
if(m==1)
{
cout<<n<<endl;
continue;
}
if( n<m+K*m)
{
cout<<0<<endl;
continue;
}
//cal : n*C(n-1-k*m,m-1)/m;
ll ret=S[n-1-K*m]*inv(S[m-1]*S[n-K*m-m]%mod,mod)%mod;
ret=ret*n%mod *inv(m,mod)%mod;
cout<<ret<<endl;
}
return 0;
}
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s) memset(a,x,(s)*sizeof a[0])
#define mem(a,x) memset(a,x,sizeof a)
#define ysk(x) (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=1e6+0.5;
ll n,m,K,S[maxn+5];
ll qb(ll a,ll n)
{
ll ans=1;
while(n)
{
if(n&1) ans=ans*a%mod;
a=a*a%mod;
n>>=1;
}
return ans;
}
ll inv(ll a,ll m)
{
return qb(a,m-2);
}
void pre()
{
S[0]=1;
for1(i,maxn)
{
S[i]=S[i-1]*i%mod;
}
}
int main()
{
std::ios::sync_with_stdio(false);
pre();
int T;cin>>T;
while(T--)
{
cin>>n>>m>>K;
if(m==1)
{
cout<<n<<endl;
continue;
}
if( n<m+K*m)
{
cout<<0<<endl;
continue;
}
//cal : n*C(n-1-k*m,m-1)/m;
ll ret=S[n-1-K*m]*inv( S[n-K*m-m]*S[m-1]%mod,mod)%mod;
ret=ret*n%mod *inv(m,mod)%mod;
cout<<ret<<endl;
}
return 0;
}