题意:求C(n,m)%p p = p1 * p2 *....*pk;
Lucas定理 + 中国剩余定理
http://blog.sina.com.cn/s/blog_12fea76590102w6ts.html
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <set>
#include <queue>
using namespace std;
#define ll long long
const int N = 20;
ll A[N], B[N];
ll q_pow(ll x,ll y, ll p){
ll ret = 1;
while(y){
if(y&1)ret = (ret*x)%p;
x = (x*x)%p;
y >>= 1;
}
return ret;
}
ll Cm(ll n, ll m, ll p){
if(n < m)return 0;
if(n == m)return 1;
if(m > n-m)m = n-m;
ll ans = 1, cn = 1, cm = 1;
while(m){
cn = (cn * n)%p;
cm = (cm * m)%p;
n--,m--;
}
ans = (cn * q_pow(cm,p-2,p))%p;
return ans;
}
ll Lucas(ll n, ll m, ll p){
if(m == 0)return 1;
return Cm(n%p,m%p,p) * Lucas(n/p, m/p, p)%p;
}
ll Ex_gcd(ll a, ll b,ll &x, ll &y){
if(b == 0){
x = 1;
y = 0;
return a;
}
ll ret = Ex_gcd(b, a%b, y, x);
y -= a/b*x;
return ret;
}
ll multi(ll a,ll b,ll p){
ll ret = 0;
while(b){
if(b&1)ret = (ret + a)%p;
a = (a+a)%p;
b>>=1;
}
return ret;
}
ll china(ll n, ll *m, ll *a){
ll M = 1, d, y, x = 0;
for(int i = 0; i < n; i++){
M *= m[i];
}
for(int i = 0; i < n; i++){
ll w = M / m[i];
d = Ex_gcd(m[i], w, d, y);
//multi(y,w,M) = w*w^-1 (w^-1)为w/m[i]%M的逆元
x = (x + multi(multi(y, w, M), a[i], M))%M;
}
return (x+M)%M;
}
int main(){
int T, k;
ll n, m;
scanf("%d",&T);
while(T--){
scanf("%lld%lld%d",&n,&m,&k);
for(int i = 0; i < k; i++){
scanf("%lld",A+i);
B[i] = Lucas(n, m, A[i]);
}
printf("%lld\n",china(k,A,B));
}
return 0;
}