设
个人收到礼物的数量分别为
,则答案为
用扩展 定理即可。
注意多次调用 时,不能直接用 和 存答案了。
#include <cstdio>
#include <cmath>
typedef long long LL;
const int N = 100005;
int n, m, p, v[6], w[6], mi[N], mo[N], c[N], cnt;
LL x, y;
int pow(int a, int b, int p) {
int res = 1;
for (; b; b >>= 1, a = 1LL * a * a % p)
if (b & 1) res = 1LL * res * a % p;
return res;
}
LL mul(LL a, LL b, LL p) {
int res = 0, f = 1;
if (a < 0) a = -a, f = -f;
if (b < 0) b = -b, f = -f;
for (; b; b >>= 1, a = (a + a) % p)
if (b & 1) res = (res + a) % p;
return res * f;
}
int exgcd(int a, int b, LL &x, LL &y) {
if (b == 0) { x = 1, y = 0; return a; }
int t = exgcd(b, a % b, y, x); y -= a / b * x; return t;
}
int inv(int a, int p) {
int t = exgcd(a, p, x, y);
return (x % p + p) % p;
}
int fac(int n, int pi, int pk) {
if (n == 0) return 1;
int res = 1;
for (int i = 2; i <= pk; ++i)
if (i % pi) res = 1LL * res * i % pk;
res = pow(res, n / pk, pk);
for (int i = 2; i <= n % pk; ++i)
if (i % pi) res = 1LL * res * i % pk;
return 1LL * res * fac(n / pi, pi, pk) % pk;
}
int calc(int n, int m, int pi, int pk) {
int up = fac(n, pi, pk), d1 = fac(m, pi, pk), d2 = fac(n - m, pi, pk);
int k = 0;
for (int i = n; i; i /= pi) k += i / pi;
for (int i = m; i; i /= pi) k -= i / pi;
for (int i = n - m; i; i /= pi) k -= i / pi;
return 1LL * pow(pi, k, pk) * up % pk * inv(d1, pk) % pk * inv(d2, pk) % pk;
}
LL excrt() {
LL t, mod, M = mo[1], C = c[1];
for (int i = 2; i <= cnt; ++i) {
t = exgcd(M, mo[i], x, y);
mod = M / t * mo[i];
x = mul(x, (c[i] - C) / t, mod);
C = (C + mul(x, M, mod)) % mod, M = mod;
}
return (C + M) % M;
}
int exlucas() {
int res = 1, lim = sqrt(p), x = p, pk;
for (int i = 2; i <= lim; ++i) {
if (x % i == 0) {
pk = 1;
while (x % i == 0) x /= i, pk *= i;
mo[++cnt] = pk, mi[cnt] = i;
}
}
if (x > 1) mo[++cnt] = mi[cnt] = x;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= cnt; ++j)
c[j] = calc(v[i], w[i], mi[j], mo[j]);
res = 1LL * res * excrt() % p;
}
return res;
}
int main() {
scanf("%d%d%d", &p, &n, &m);
v[0] = n;
for (int i = 1; i <= m; ++i) {
scanf("%d", &w[i]);
v[i] = v[i-1] - w[i-1];
if (v[i] < w[i]) { puts("Impossible"); return 0; }
}
printf("%d\n", exlucas());
return 0;
}