一眼答案( tot 是 wi 的和
(
n
t
o
t
)
∗
(
t
o
t
w
m
)
∗
…
∗
(
w
1
w
1
)
\tbinom{n}{tot} * \tbinom{tot}{w_m} * … * \tbinom{w_1}{w_1}
(totn)∗(wmtot)∗…∗(w1w1)
其实这里就可以直接exLucas板子了
但其实可以更简单
然后拆一下式子
!
(
n
)
/
!
(
n
−
t
o
t
)
/
!
(
t
o
t
)
∗
!
(
t
o
t
)
/
!
(
t
o
t
−
w
m
)
/
!
(
w
m
)
…
…
!(n) / !(n - tot) / !(tot) * !(tot) / !(tot - w_m) / !(w_m) ……
!(n)/!(n−tot)/!(tot)∗!(tot)/!(tot−wm)/!(wm)……
然后发现可以消掉
!
(
n
)
/
!
(
n
−
t
o
t
)
/
!
(
w
m
)
…
…
/
!
(
w
1
)
!(n) / !(n - tot) / !(w_m) …… / !(w_1)
!(n)/!(n−tot)/!(wm)……/!(w1)
然后现在就是要求这个别致的小东西了
注意模数不是质数哦
需要exgcd求逆元 CRT(中国剩余定理)合并
懒得写了
实现可以参考一下这篇博客
附上代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1e5 + 2;
long long P, ans;
long long n, m, w[10], tot;
void exgcd(long long a, long long b, long long& x, long long& y){
if(!b){x = 1, y = 0; return ;}
exgcd(b, a % b, y, x); y -= (a / b) * x;
}//ok
long long inv(long long a, long long b){
long long x, y;
exgcd(a, b, x, y);
x = (x % b + b) % b;
return x;
}//ok
long long qpow(long long x, long long y, long long mod){
long long res = 1;
while(y){
if(y & 1) res = res * x % mod;
y >>= 1; x = x * x % mod;
}
return res;
}//ok
long long fac(long long x, long long p1, long long p2){
if(!x) return 1;
long long res = 1;
for(int i = 2; i <= p2; ++i)
if(i % p1) res = res * i % p2;
res = qpow(res, x / p2, p2);
for(int i = 2; i <= x % p2; ++i)
if(i % p1) res = res * i % p2;
return res * fac(x / p1, p1, p2) % p2;
}//ok
struct P{
long long w;
long long s1[N], s2[N];
int top;
long long CRT(long long x, long long p2){
return x * (w / p2) % w * inv(w / p2, p2) % w;
}
void init(){
int x = w;
for(int i = 2; i * i <= w; ++i)
if(!(x % i)){
s1[++top] = i;
s2[top] = 1;
while(!(x % i)){x /= i; s2[top] *= i;}
}
if(x > 1){
s1[++top] = x; s2[top] = x;
}
}
}p;//ok
long long solve(long long p1, long long p2){
long long res = 1;
res = fac(n, p1, p2) * inv(fac(n - tot, p1, p2), p2) % p2;
for(int i = 1; i <= m; ++i)
res = res * inv(fac(w[i], p1, p2), p2) % p2;
long long cnt = 0;
for(long long i = n; i; i /= p1) cnt += i / p1;
for(long long i = n - tot; i; i /= p1) cnt -= i / p1;
for(int j = 1; j <= m; ++j){
for(long long i = w[j]; i; i /= p1) cnt -= i / p1;
}
return p.CRT(res * qpow(p1, cnt, p2), p2);
}
int main() {
scanf("%lld%lld%lld", &p.w, &n, &m);
p.init();
for(int i = 1; i <= m; ++i){
scanf("%lld", &w[i]);
tot += w[i];
}
if(tot > n){
printf("Impossible\n");
return 0;
}
for(int i = 1; i <= p.top; ++i){
//printf("%d %lld %lld\n", p.top, p.s1[i], p.s2[i]);
ans = (ans + solve(p.s1[i], p.s2[i])) % p.w;//这里要记得取模啊qvq
}
printf("%lld", ans);
return 0;
}