E - Diverse Group
It’s the year 3018 and you are the head of the Bioinformation Articulation in Cosmic Space (BACS) program at NASA. Under this program, NASA has decided to send K humans to planet Naboo. The whole of humanity is very excited about this and everyone wants to be a part of this voyage. But alas, there is only room for K people. Now, there are N regions in planet Earth. NASA asked each of these regions to compile a list of M people from that region who would be fit for this journey. The listing is complete and now you have the N lists at your disposal (one for each region, each containing M people). Among these N*M people, you want to select K people for this journey. But you want to make the selected group as diverse as possible. Therefore, you have decided not to select two person from the same region. Being a math enthusiast, you want to know how many different ways you can make this group. Two groups are different if there is someone who is in one group but not in the other.
Input Specifications
The first line contains a positive integer T (T ≤ 1000) denoting the number of test cases. In each of the following T lines, there will be three space separated integers N, M & K where N denotes the number of regions, M denotes the number of people from that region and K denotes the number of people who will sent to planet Naboo.
Constraints
2 ≤ N,M ≤ 10000000
1 ≤ K ≤ N*M
Outputput Specification:
For each case, print the number of ways you can make that group. Since the answer can be rather big, print the answer modulo 1000000007 (10^9 + 7).
Input
5
2 2 1
2 3 2
3 2 5
4 2 3
5 4 4
Output
4
9
0
32
1280
题意:给你三个整数 N,M,K , 大概可以理解为 N 个队,每一队有 M 个人,然后需要 取 K 个人 出来,但是 每一个队 只能取一个人 或者 不取。 问最后 有多少种 方案。 最后对 1e9 + 7 取模。
思路:其实这个题思路不难, 答案就是 C(N,K) * M^K。 主要是算 组合数取模。这里 组合数取模 用的 乘法逆元 计算的。
关于乘法逆元求组合数取模。。 最后就是 M^K, 很明显 用快速幂。
AC代码:
#include<cstdio>
using namespace std;
typedef long long LL;
const LL maxn = 1e7 + 100,mod = 1e9 + 7;
LL Jc[maxn];
void calJc() //求maxn以内的数的阶乘
{
Jc[0] = Jc[1] = 1;
for(LL i = 2; i < maxn; i++)
Jc[i] = Jc[i - 1] * i % mod;
}
//费马小定理求逆元
LL pow(LL a, LL n, LL p) //快速幂 a^n % p
{
LL ans = 1;
while(n)
{
if(n & 1)
ans = ans * a % p;
a = a * a % p;
n >>= 1;
}
return ans;
}
LL niYuan(LL a, LL b) //费马小定理求逆元
{
return pow(a, b - 2, b);
}
LL C(LL a, LL b) //计算C(a, b)
{
return Jc[a] * niYuan(Jc[b], mod) % mod
* niYuan(Jc[a - b], mod) % mod;
}
int main()
{
int t;
scanf("%d",&t);
calJc();
while(t --)
{
LL n,m,k;
scanf("%I64d%I64d%I64d",&n,&m,&k);
if(n >= k) printf("%I64d\n",C(n,k) * pow(m,k,mod) % mod);
else printf("0\n");
}
return 0;
}