HDU 5894 hannnnah_j’s Biologica(lucas定理求组合数+乘法逆元)——2016 ACM/ICPC Asia Regional Shenyang Online
2016-09-19 00:38
447 查看
此文章可以使用目录功能哟↑(点击上方[+])
Accept: 0 Submit: 0
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
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.
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
For each test case the output is only one integer number ans in a line.
2
4 2 6
5 2 1
0
5
解题思路:
【题意】
n个位置围成环,m个人坐,要求相邻两个人之间必须至少隔k个位置
问有多少种坐法,结果对1e9+7取模
【类型】
lucas定理求组合数+乘法逆元
【分析】
其实此题可以这么理解
![](https://img-blog.csdn.net/20160919002401398)
假定一个人已经坐在了某个位置,如图所示
那还剩下n-1个位置,而要求相邻两人之间必须隔k个位置,所以m个人就有m*k个位置不能坐
那剩下的位置数为n-1-m*k,由于一个人已经坐好,那我需要从这些剩下的位置中挑选出m-1个位置供剩下的m-1个人就坐
故组合数为C(n-m*k-1,m-1)
然后因为有n个位置,所以第一个人位置的选法就有n种
再考虑此题中每个人都是一样的,即不同方案仅仅是坐的位置序列不同,那上述做法会重复计算m次
比如有3个人,假设他们坐的位置是(2,4,7),那么,(4,2,7),(7,2,4)是重复计算的
故方案数的最终式子应为[C(n-m*k-1,m-1)*n/m]%1000000007
那求解组合数不用想肯定得用lucas定理,毕竟n和m有点大,直接打表已经存不下结果,且会超时
而除法取模部分,考虑到1000000007是质数,且m<1000000007,所以gcd(m,1000000007)=1,故可以直接采取乘法逆元
【时间复杂度&&优化】
![](https://img-blog.csdn.net/20160919003628070)
题目链接→HDU 5894 hannnnah_j’s Biologica
/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 1000005;
const int M = 100005;
const int inf = 1000000007;
const int mod = 1000000007;
__int64 fac
;
void init()//预处理阶乘
{
fac[0]=1;
for(int i=1;i<=N;i++)
fac[i]=i*fac[i-1]%mod;
}
__int64 pow_mod(__int64 a,__int64 b)
{
__int64 s=1;
a=a%mod;
while(b)
{
if(b&1)
s=s*a%mod;
a=a*a%mod;
b>>=1;
}
return s;
}
__int64 C(int n,int m)
{
if(m>n)
return 0;
return fac
*pow_mod(fac[m]*fac[n-m]%mod,mod-2)%mod;
}
__int64 Lucas(int n,int m)
{
if(m==0)
return 1;
return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;
}
__int64 Quick_Mod(int a,int b)//快速幂
{
__int64 res = 1,term = a % mod;
while(b)
{
if(b & 1) res = (res * term) % mod;
term = (term * term) % mod;
b >>= 1;
}
return res;
}
int main()
{
int t,n,m,k;
init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
printf("%I64d\n",((Lucas(n-m*k-1,m-1)*n)%mod)*Quick_Mod(m,mod-2)%mod);
}
return 0;
}菜鸟成长记
![](http://acm.fzu.edu.cn/image/problem.gif)
HDU 5894 hannnnah_j’s Biologica
Accept: 0 Submit: 0Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
![](http://acm.fzu.edu.cn/image/prodesc.gif)
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.
![](http://acm.fzu.edu.cn/image/prodesc.gif)
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
![](http://acm.fzu.edu.cn/image/prodesc.gif)
Output
For each test case the output is only one integer number ans in a line.
![](http://acm.fzu.edu.cn/image/prodesc.gif)
Sample Input
24 2 6
5 2 1
![](http://acm.fzu.edu.cn/image/prodesc.gif)
Sample Output
05
![](http://acm.fzu.edu.cn/image/prodesc.gif)
Problem Idea
解题思路:【题意】
n个位置围成环,m个人坐,要求相邻两个人之间必须至少隔k个位置
问有多少种坐法,结果对1e9+7取模
【类型】
lucas定理求组合数+乘法逆元
【分析】
其实此题可以这么理解
假定一个人已经坐在了某个位置,如图所示
那还剩下n-1个位置,而要求相邻两人之间必须隔k个位置,所以m个人就有m*k个位置不能坐
那剩下的位置数为n-1-m*k,由于一个人已经坐好,那我需要从这些剩下的位置中挑选出m-1个位置供剩下的m-1个人就坐
故组合数为C(n-m*k-1,m-1)
然后因为有n个位置,所以第一个人位置的选法就有n种
再考虑此题中每个人都是一样的,即不同方案仅仅是坐的位置序列不同,那上述做法会重复计算m次
比如有3个人,假设他们坐的位置是(2,4,7),那么,(4,2,7),(7,2,4)是重复计算的
故方案数的最终式子应为[C(n-m*k-1,m-1)*n/m]%1000000007
那求解组合数不用想肯定得用lucas定理,毕竟n和m有点大,直接打表已经存不下结果,且会超时
而除法取模部分,考虑到1000000007是质数,且m<1000000007,所以gcd(m,1000000007)=1,故可以直接采取乘法逆元
【时间复杂度&&优化】
题目链接→HDU 5894 hannnnah_j’s Biologica
![](http://acm.fzu.edu.cn/image/prodesc.gif)
Source Code
/*Sherlock and Watson and Adler*/#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 1000005;
const int M = 100005;
const int inf = 1000000007;
const int mod = 1000000007;
__int64 fac
;
void init()//预处理阶乘
{
fac[0]=1;
for(int i=1;i<=N;i++)
fac[i]=i*fac[i-1]%mod;
}
__int64 pow_mod(__int64 a,__int64 b)
{
__int64 s=1;
a=a%mod;
while(b)
{
if(b&1)
s=s*a%mod;
a=a*a%mod;
b>>=1;
}
return s;
}
__int64 C(int n,int m)
{
if(m>n)
return 0;
return fac
*pow_mod(fac[m]*fac[n-m]%mod,mod-2)%mod;
}
__int64 Lucas(int n,int m)
{
if(m==0)
return 1;
return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;
}
__int64 Quick_Mod(int a,int b)//快速幂
{
__int64 res = 1,term = a % mod;
while(b)
{
if(b & 1) res = (res * term) % mod;
term = (term * term) % mod;
b >>= 1;
}
return res;
}
int main()
{
int t,n,m,k;
init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
printf("%I64d\n",((Lucas(n-m*k-1,m-1)*n)%mod)*Quick_Mod(m,mod-2)%mod);
}
return 0;
}菜鸟成长记
相关文章推荐
- 2016 ACM/ICPC Asia Regional Shenyang Online 1003/HDU 5894 数学/组合数/逆元
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5894 hannnnah_j’s Biological Test
- HDU 5446 Unknown Treasure(lucas定理+中国剩余定理)——2015 ACM/ICPC Asia Regional Changchun Online
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5895 Mathematician QSC(矩阵快速幂+高次幂取模)★ ★
- HDU 5901 Count Primes (模板 + 数论知识)——2016 ACM/ICPC Asia Regional Shenyang Online
- HDU 5900 QSC and Master(2016 ACM/ICPC Asia Regional Shenyang Online)
- HDU 5898 odd-even number(2016 ACM/ICPC Asia Regional Shenyang Online)
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5895 Mathematician QSC
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5900 QSC and Master(区间dp水题)
- HDU 5898&&2016 ACM/ICPC Asia Regional Shenyang Online/ odd-even number [数位DP]【动态规划】
- HDU 5895&&2016 ACM/ICPC Asia Regional Shenyang Online1004 Mathematician QSC [矩阵加速+欧拉降幂]【数论】
- hdu 5900 QSC and Master 区间dp(2016 ACM/ICPC Asia Regional Shenyang Online)
- HDU 5895 Mathematician QSC(逆元应用+矩阵快速幂+数论知识)——2016 ACM/ICPC Asia Regional Shenyang Online
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5898 odd-even number
- 2016 ACM/ICPC Asia Regional Shenyang Online 1009/HDU 5900 区间dp
- HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)——2016 ACM/ICPC Asia Regional Shenyang Online
- HDU 5898 odd-even number (数位DP) 2016 ACM/ICPC Asia Regional Shenyang Online
- 2016 ACM/ICPC Asia Regional Shenyang Online hannnnah_j’s Biological Test【组合数学】
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5893 List wants to travel
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5901 Count Primes (模板 + 数论知识)★