【hdu 5894】【组合数学 lucas 费马小求逆元】 【m个人坐n个围成一周的位置每个人距离至少为k,求方法数】

来源:互联网 发布:一骑当千动作数据 编辑:程序博客网 时间:2024/05/17 06:35

传送门:HDU5894 hannnnah_j’s Biological Test

描述:

hannnnah_j’s Biological Test

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 974    Accepted Submission(s): 338


Problem Description
hannnnah_j is a teacher in WL High school who teaches biology.

One day, she wants to test m students, thus she arranges n different seats around a round table.

In order to prevent cheating, she thinks that there should be at least k empty seats between every two students.

hannnnah_j is poor at math, and she wants to know the sum of the solutions.So she turns to you for help.Can you help her? The answer maybe large, and you need to mod 1e9+7.
 

Input
First line is an integer T(T≤1000).
The next T lines were given n, m, k, respectively.
0 < m < n < 1e6, 0 < k < 1000
 

Output
For each test case the output is only one integer number ans in a line.
 

Sample Input
24 2 65 2 1
 

Sample Output
05
 

Source
2016 ACM/ICPC Asia Regional Shenyang Online
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5899 5897 5896 5893 5892 
题意:

m个人坐n个围成一周的位置每个人距离至少为k,求方法数

思路:

首先确定第一个人的位置,第一个人可以从n个椅子中任选一个,然后剩余n-1个椅子。因为人的间隔至少k个椅子,所以从这些符合要求的间隔距离的椅子抽出k*m个,然后剩下的m-1个人就可以随便从剩下的椅子人选了。可以想象成每个人和k个座位捆绑在一起,一旦这个人有了座位,他后面自动添加这k个座位。
那么第一个人从n个座位中选择一个,并且抽走了k*m个,那么剩下n-1-k*m个座位,在这之中选m-1个作为给其余人座,总数为sum=n*C(n-1-k*m,m-1),因为这里的人是无差别的。比如有3个人,假设他们坐的位置是(2,4,7),那么,(4,2,7),(7,2,4)是重复计算的,所以最后结果是sum/m。

代码:

#include<bits/stdc++.h>#define ll __int64using namespace std;const ll p=1e9+7;ll pow_mod(ll x, ll n){    ll res=1;    while(n>0){        if(n&1)res=res*x%p;        x=x*x%p;        n>>=1;    }    return res;}ll cm(ll n,ll m,ll mod){    if(m>n) return 0;    ll i,ans=1,a,b;    for(i=0; i<m; i++){        a=(n-i)%mod;        b=(m-i)%mod;        ans=ans*( a*pow_mod(b,mod-2)%mod )%mod;    }    return ans;}ll lucas(ll n,ll m,ll p){    if(m==0) return 1;    return ( cm(n%p, m%p, p)*lucas(n/p, m/p, p) )%p;}int main(){  int T;  ll n,m,k;  scanf("%d",&T);  while( T-- ){    scanf("%lld%lld%lld",&n,&m,&k);    ll a=lucas(n-m*k-1, m-1, p);    ll b=pow_mod(m, p-2)%p;    printf("%I64d\n",((a*n)%p*b)%p);  }  return 0;}



1 0
原创粉丝点击