Unknown Treasure
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1992 Accepted Submission(s): 732
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
solution:
Lucas定理求C(n,m)%M,而中国剩余定理刚好解决后面部分。利用Lucas定理求出所有对pi取模的值,然后在用中国剩余定理求解。
这是会数论的队友zys写的,膜~
#include<stdio.h> #define ll long long #define ull unsigned long long ll p[20],a[20]; ll n, m, k; ll inv(ll a,ll MOD) { return a == 1 ? 1 : (MOD - MOD / a) * inv(MOD % a,MOD) % MOD; } ll C(ll n, ll m,ll MOD) { if (m < 0) return 0; if (n < m) return 0; if (m > n - m) m = n - m; ll up = 1, down = 1; for (ll i = 0; i < m; i++) { up = up * (n - i) % MOD; down = down * (i + 1) % MOD; } return up * inv(down,MOD) % MOD; } ll Lucas(ll n, ll m, ll p) { ll ret = 1; while (n && m) { ll a = n % p, b = m % p; if (a < b) return 0; ret = ret * C(a, b, p) % p; n /= p; m /= p; } return ret; } ll extend_gcd(ll a, ll b, ll& x, ll& y) { ll d = a; if (b != 0) { d = extend_gcd(b, a%b, y, x); y -= (a / b)*x; } else { x = 1; y = 0; } return d; } ll qmul(ll a, ll b, ll MOD) { ull ans=0; ull tem = a; while (b) { if (b & 1)ans = (ans + tem) % MOD; b >>= 1; tem = (tem * 2) % MOD; } return (ll)ans; } ll CRT() { ll M = 1, Mi; ll x, y, d, ans = 0; for (int i = 0; i < k; i++) M *= p[i]; for (int i = 0; i < k; i++) { Mi = M / p[i]; d = extend_gcd(Mi, p[i], x, y); ans = (ans + qmul(qmul(Mi,(x+p[i])%p[i],M),a[i],M)) % M; } if (ans < 0) ans += M; return ans; } int main() { int T; scanf("%d", &T); while (T--) { scanf("%I64d%I64d%I64d", &n, &m, &k); for (int i = 0; i < k; i++) { scanf("%I64d", &p[i]); a[i] = Lucas(n, m, p[i]); } printf("%I64d\n", CRT()); } }