hdu-5894-hannnnah_j’s Biological Test(Lucas定理+乘法逆+组合数)
2016-09-29 13:45
721 查看
hannnnah_j’s Biological Test
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
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
2
4 2 6
5 2 1
Sample Output
0
5
题意:
给一个m个学生在长度为n的环形摆放的座位安排座位,要求相邻两个学生座位之间的距离至少是k,交换两个学生后的摆放和原来一样视为同种方案,求总方案数%1e9+7。
题目链接:hannnnah_j’s Biological Test
解题思路:
先从n个座位选一个出来,符合条件的方案,必须有k*m个空座位,那么接下来只需从n-1+k*m个座位中选出m-1个同
学的座位即可,第一个位置有n种选法,但因为学生都是一样的,同种方案会被不同的学生选到,即选了m次,删去重
复答案为n*C(n-k*m-1, m-1)/m % (1e9+7)。
计算组合数取模可以套用Lucas模板,在模mod下,a/b %mod 与 a*(b)的逆 同余数,用inv(m,mod)求解模mod下m的
逆(Lrj 训练指南122)。
代码:
#include<cstdio>
using namespace std;
typedef long long LL;
const int N = 1e6+5;
const LL mod = 1e9+7;
LL fac[N+10];
LL pow_mod(LL x, LL n)//快速幂取模
{
LL sum = 1;
while(n) {
if(n & 1) sum = sum * x % mod;
x = x * x % mod;
n >>= 1;
}
return sum;
}
void init()//初始化所需要的阶乘
{
fac[0] = 1;
for(int i = 1;i <= N;i++)
fac[i] =fac[i-1] * i % mod;
}
LL Lucas(LL n, LL m)//Lucas定理,计算C(n,m)%mod
{
LL ans = 1;
while(n && m) {
LL a = n % mod, b = m % mod;
if(a < b) return 0;
ans = ans * fac[a] * pow_mod(fac[b]*fac[a-b] % mod, mod-2) % mod;
n /= mod;
m /= mod;
}
return ans;
}
void exd_gcd(LL a, LL b, LL& d, LL& x, LL& y)//拓展欧几里得解方程ax+by=gcd(a,b);
{
if(!b) {
d = a;
x = 1;
y = 0;
}
else {
exd_gcd(b, a%b, d, y, x);
y -= x*(a/b);
}
}
LL inv(LL a, LL n)//计算模n下a的逆元,如果不存在,返回-1
{
LL d, x, y;
exd_gcd(a, n, d, x, y);
return d == 1? (x+n)%n : -1;
}
int main()
{
int T;
LL n, m, k;
init();
scanf("%d",&T);
while(T--) {
scanf("%I64d%I64d%I64d",&n, &m, &k);
if(m == 1) {
printf("%I64d\n",n);
continue;
}
printf("%I64d\n",(n * Lucas(n-k*m-1, m-1) % mod) * inv(m, mod) % mod);
}
return 0;
}
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
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
2
4 2 6
5 2 1
Sample Output
0
5
题意:
给一个m个学生在长度为n的环形摆放的座位安排座位,要求相邻两个学生座位之间的距离至少是k,交换两个学生后的摆放和原来一样视为同种方案,求总方案数%1e9+7。
题目链接:hannnnah_j’s Biological Test
解题思路:
先从n个座位选一个出来,符合条件的方案,必须有k*m个空座位,那么接下来只需从n-1+k*m个座位中选出m-1个同
学的座位即可,第一个位置有n种选法,但因为学生都是一样的,同种方案会被不同的学生选到,即选了m次,删去重
复答案为n*C(n-k*m-1, m-1)/m % (1e9+7)。
计算组合数取模可以套用Lucas模板,在模mod下,a/b %mod 与 a*(b)的逆 同余数,用inv(m,mod)求解模mod下m的
逆(Lrj 训练指南122)。
代码:
#include<cstdio>
using namespace std;
typedef long long LL;
const int N = 1e6+5;
const LL mod = 1e9+7;
LL fac[N+10];
LL pow_mod(LL x, LL n)//快速幂取模
{
LL sum = 1;
while(n) {
if(n & 1) sum = sum * x % mod;
x = x * x % mod;
n >>= 1;
}
return sum;
}
void init()//初始化所需要的阶乘
{
fac[0] = 1;
for(int i = 1;i <= N;i++)
fac[i] =fac[i-1] * i % mod;
}
LL Lucas(LL n, LL m)//Lucas定理,计算C(n,m)%mod
{
LL ans = 1;
while(n && m) {
LL a = n % mod, b = m % mod;
if(a < b) return 0;
ans = ans * fac[a] * pow_mod(fac[b]*fac[a-b] % mod, mod-2) % mod;
n /= mod;
m /= mod;
}
return ans;
}
void exd_gcd(LL a, LL b, LL& d, LL& x, LL& y)//拓展欧几里得解方程ax+by=gcd(a,b);
{
if(!b) {
d = a;
x = 1;
y = 0;
}
else {
exd_gcd(b, a%b, d, y, x);
y -= x*(a/b);
}
}
LL inv(LL a, LL n)//计算模n下a的逆元,如果不存在,返回-1
{
LL d, x, y;
exd_gcd(a, n, d, x, y);
return d == 1? (x+n)%n : -1;
}
int main()
{
int T;
LL n, m, k;
init();
scanf("%d",&T);
while(T--) {
scanf("%I64d%I64d%I64d",&n, &m, &k);
if(m == 1) {
printf("%I64d\n",n);
continue;
}
printf("%I64d\n",(n * Lucas(n-k*m-1, m-1) % mod) * inv(m, mod) % mod);
}
return 0;
}
相关文章推荐
- HDU 5894-hannnnah_j’s Biological Test(大组合数模板Lucas)
- 2016 ACM/ICPC Reginal Shengyang hdu 5894 hannnnah_j’s Biological Test (数学推导 Lucas)
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5894 hannnnah_j’s Biological Test
- hannnnah_j’s Biological Test (lucas定理 )
- hdu 5894 hannnnah_j’s Biological Test 排列组合
- HDU 5894 hannnnah_j’s Biological Test (组合数学 + 快速幂 + 乘法逆元)
- HDU 5894 hannnnah_j’s Biological Test(组合数学 逆元)
- 沈阳网赛1003 HDU 5894 hannnnah_j’s Biological Test
- hdu 5894 hannnnah_j’s Biological Test
- HDU 5894 hannnnah_j’s Biologica(lucas定理求组合数+乘法逆元)——2016 ACM/ICPC Asia Regional Shenyang Online
- HDU 5894 hannnnah_j’s Biological Test
- hannnnah_j’s Biological Test HDU - 5894
- hdu_5894_hannnnah_j’s Biological Test(打表找规律)
- HDU-5894-hannnnah_j’s Biological Test(组合数取模)
- hdu 5446 Lucas定理,中国剩余定理,处理爆long long 的乘法取模运算
- hdu 5446 长春区域赛网络赛1010 Unknown Treasure(lucas定理+中国剩余定理+移位乘法)
- HDU 5446 Lucas + 中国剩余定理 + 快速乘法
- HDU 5446 Unknown Treasure(lucas + 中国剩余定理 + 模拟乘法)
- hannnnah_j’s Biological Test HDU - 5894 组合数学&&小球问题
- HDU 4349——Xiao Ming's Hope——————【Lucas定理】