Unknown TreasureTime Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1820 Accepted Submission(s): 671
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} .
Output
For each test case output the correct combination on a line.
Sample Input
Sample Output
|
题意:求解C(n, m) % (p[0] * p[1] * p[2] * ... * p[k-1])。 其中p[]是不同的质数。
思路:由于p[0] * p[1] * ... * p[k-1]很大,所以不不能直接用lucas。
考虑把每个质数分开。
C(n, m) % p[0] = a[0], C(n, m) % p[1] = a[1]... C(n, m) % p[k-1] = a[k-1]。
这样得到下面方程组
A = a[0] (mod p[0])
A = a[1] (mod p[1])
...
A = a[k-1] (mod p[k-1])。
下面用CRT直接求出A就可以了。
因为题目没有说结果是正整数,所以CRT最后解为0时,直接返回。这里WA了3次 o(╯□╰)o
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> #define LL long long #define debug printf("1\n"); using namespace std; struct ONE { LL gcd(LL a, LL b){ return b == 0 ? a : gcd(b, a%b); } LL lcm(LL a, LL b){ return a / gcd(a, b) * b; } void exgcd(LL a, LL b, LL &d, LL &x, LL &y) { if(b == 0) {d = a, x = 1, y = 0;} else { exgcd(b, a%b, d, y, x); y -= x * (a / b); } } LL CRT(LL l, LL r, LL *a, LL *m) { LL LCM = 1; for(LL i = l; i <= r; i++) LCM = LCM / gcd(LCM, m[i]) * m[i]; for(LL i = l+1; i <= r; i++) { LL d, x, y, A = m[l], B = m[i], c = a[i] - a[l]; exgcd(A, B, d, x, y); if(c % d) return -1; LL mod = m[i] / d; LL k = ((x / d * c) % mod + mod) % mod; a[l] = m[l] * k + a[l]; m[l] = m[l] / d * m[i]; } //if(a[l] == 0) 这句话不能加 // return LCM; return a[l]; } }; ONE crt; LL fac[100000+10]; void getfac(LL p) { fac[0] = 1 % p; for(LL i = 1; i <= p; i++) fac[i] = fac[i-1] * i % p; } struct TWO { LL pow_mod(LL a, LL n, LL p) { LL ans = 1 % p; while(n) { if(n & 1) ans = ans * a % p; a = a * a % p; n >>= 1; } return ans; } LL C(LL n, LL m, LL p) { if(n < m) return 0; else return fac[n] * pow_mod(fac[m]*fac[n-m]%p, p-2, p) % p; } LL Lucas(LL n, LL m, LL p) { if(m == 0) return 1 % p; else return C(n%p, m%p, p) * Lucas(n/p, m/p, p) % p; } }; TWO LUCAS; LL p[15], a[15], m[15]; int main() { LL t; scanf("%d", &t); while(t--) { LL N, M, k; scanf("%lld%lld%lld", &N, &M, &k); for(LL i = 0; i < k; i++) { scanf("%lld", &p[i]); m[i] = p[i]; getfac(p[i]); a[i] = LUCAS.Lucas(N, M, p[i]); } printf("%lld\n", crt.CRT(0, k-1, a, p)); } return 0; }