题目链接:点击这里
题意:求 Cmn%M,(M=m1∗…mp且mi都是质数) 。
用Lucas定理求出 Cmn%mi=ai ,然后用中国剩余定理求此方程组。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define maxn 100005
long long a[maxn], b[maxn];
long long n, m;
int p;
long long qpow (long long a, long long b, long long mod) {
long long ret=1;
while (b) {
if (b&1) ret = (ret*a)%mod;
a = (a*a)%mod;
b >>= 1;
}
return ret;
}
long long fac[maxn];
void get_fact (long long p) {
fac[0] = 1;
for (int i = 1; i <= p; i++)
fac[i] = (fac[i-1]*i)%p;
}
long long Lucas (long long n, long long m, long long p) {
long long ret=1;
while (n&&m) {
long long a=n%p,b=m%p;
if (a < b) return 0;
ret = (ret*fac[a]* qpow (fac[b]*fac[a-b]%p,p-2,p))%p;
n /= p;
m /= p;
}
return ret;
}
void gcd (long long a, long long b, long long &d, long long &x, long long &y) {
if (!b) {
d = a;
x = 1;
y = 0;
}
else {
gcd (b, a%b, d, y, x);
y -= x*(a/b);
}
}
long long mul (long long a, long long b, long long mod) {
if (b == 0)
return 0;
long long ans = mul (a, b>>1, mod);
ans = ans*2%mod;
if (b&1) ans += a, ans %= mod;
return ans;
}
long long china (int n, long long *a, long long *m) {
long long M = 1, d, y, x = 0;
for (int i = 0; i < n; i++) M *= m[i];
for (int i = 0; i< n; i++) {
long long w = M/m[i];
gcd (m[i], w, d, d, y);
x = (x+ mul (mul (y, w, M), a[i], M)) % M;
}
return (x+M) % M;
}
void solve () {
for (int i = 0; i < p; i++) {
get_fact (a[i]);
b[i] = Lucas (n, m, a[i]);
}
printf ("%lld\n", china (p, b, a));
}
int main () {
int t;
scanf ("%d", &t);
while (t--) {
scanf ("%lld%lld%d", &n, &m, &p);
for (int i = 0; i < p; i++) scanf ("%lld", &a[i]);
solve ();
}
return 0;
}