Unknown Treasure
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 168 Accepted Submission(s): 40
Problem Description
On the way to the next secret treasure hiding place, the mathematician discovered a cave unknown to the map. The mathematician entered the cave because it is there. Somewhere deep in the cave, she found a treasure chest with a combination lock and some numbers on it. After quite a research, the mathematician found out that the correct combination to the lock would be obtained by calculating how many ways are there to pick
m
different apples among
n
of them and modulo it with
M
.
M
is the product of several different primes.
Input
On the first line there is an integer
T(T≤20)
representing the number of test cases.
Each test case starts with three integers n,m,k(1≤m≤n≤1018,1≤k≤10) on a line where k is the number of primes. Following on the next line are k different primes p1,...,pk . It is guaranteed that M=p1·p2···pk≤1018 and pi≤105 for every i∈{1,...,k} .
Each test case starts with three integers n,m,k(1≤m≤n≤1018,1≤k≤10) on a line where k is the number of primes. Following on the next line are k different primes p1,...,pk . It is guaranteed that M=p1·p2···pk≤1018 and pi≤105 for every i∈{1,...,k} .
Output
For each test case output the correct combination on a line.
Sample Input
1 9 5 2 3 5
Sample Output
6
Source
解题报告:2015长春网络赛。求C(n, m) % (∏pi)。pi小于10^5,m, n, 以及答案都是10^18。
先使用Lucas定理求出对于每个pi,C(n, m) % pi的值。再使用中国剩余定理对模数和余数求解即可。代码如下:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <functional>
#include <cassert>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ff(i, n) for(int i=0,END=(n);i<END;i++)
#define fff(i, n, m) for(int i=(n),END=(m);i<=END;i++)
#define dff(i, n, m) for(int i=(n),END=(m);i>=END;i--)
#define mid ((l+r)/2)
#define bit(n) (1ll<<(n))
#define clr(a, b) memset(a, b, sizeof(a))
#define debug(x) cout << #x << " = " << x << endl;
#define ls (rt << 1)
#define rs (ls | 1)
#define lson l, m, ls
#define rson m + 1, r, rs
void work();
int main() {
work();
return 0;
}
/**************************Beautiful GEGE**********************************/
ll n, m;
int k;
ll p[11], r[11];
const int maxp = 1e5 + 5;
ll fact[maxp] = {0, 1};
ll inv[maxp] = {0, 1};
ll pow_mod(ll a, int b, int mod) {
ll ret = 1;
while (b) {
if (b & 1) ret = ret * a % mod;
b >>= 1;
a = a * a % mod;
}
return ret;
}
void gcd(ll a, ll b, ll &d, ll &x, ll &y)
{
if (b == 0) {
d = a, x = 1, y = 0;
} else {
gcd(b, a%b, d, y, x);
y -= x * (a / b);
}
}
/* m: divisor, a: remainder */
ll china(ll n, ll m[], ll a[])
{
ll aa = a[0];
ll mm = m[0];
ff(i, n) {
ll sub = (a[i] - aa);
ll d, x, y;
gcd(mm, m[i], d, x, y);
if (sub % d) return -1;
ll new_m = m[i] / d;
new_m = (sub / d * x % new_m + new_m) % new_m;
aa = mm * new_m + aa;
mm = mm * m[i] / d;
}
aa = (aa + mm) % mm;
return aa;
}
void input() {
cin >> n >> m >> k;
ff(i, k) {
int mod;
scanf("%d", &mod);
fff(j, 2, mod - 1) fact[j] = fact[j - 1] * j % mod;
inv[mod - 1] = pow_mod(fact[mod - 1], mod - 2, mod);
dff(j, mod - 1, 1) inv[j - 1] = inv[j] * j % mod;
assert(inv[1] == 1);
int ret = 1;
ll mm = m, nn = n;
while(mm && nn) {
int mod_n = nn % mod, mod_m = mm % mod;
if (mod_n >= mod_m) {
ret = ret * fact[mod_n] % mod * inv[mod_m] % mod * inv[mod_n - mod_m] % mod;
} else {
ret = 0;
break;
}
mm /= mod, nn /= mod;
}
p[i] = mod;
r[i] = ret;
}
cout << china(k, p, r) << endl;
}
void work() {
int T; scanf("%d", &T);
fff(cas, 1, T) {
input();
/* solve(); */
}
}