1. 程式人生 > >【LG2183】[國家集訓隊]禮物

【LG2183】[國家集訓隊]禮物

【LG2183】[國家集訓隊]禮物

題面

洛谷

題解

插曲:不知道為什麼,一看到這個題目,我就想到了這個人。。。
如果不是有\(exLucas\),這題就是\(sb\)題。。。
首先,若\(\sum_{i=1}^mw_i>n\)就直接\(Impossible\)
然後我們考慮怎麼求方案,其實很簡單啊。。。
就是
\[ ans=\prod_{i=1}^m(n-\sum_{j=1}^{i-1}w_j) \]
因為模數小,要用\(exLucas\)
程式碼

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
using namespace std; 
typedef long long ll; 
ll exgcd(ll a, ll b, ll &x, ll &y) {
    if (!b) return x = 1, y = 0, a; 
    ll res = exgcd(b, a % b, x, y), t;
    t = x, x = y, y = t - a / b * y; 
    return res; 
} 
ll fpow(ll x, ll y, ll Mod) { 
    ll res = 1; 
    while (y) { 
        if (y & 1ll) res = res * x % Mod; 
        x = x * x % Mod; 
        y >>= 1ll; 
    }
    return res; 
} 
ll fac(ll n, ll pi, ll pk) { 
    if (!n) return 1; 
    ll res = 1; 
    for (ll i = 2; i <= pk; i++) 
        if (i % pi) res = res * i % pk; 
    res = fpow(res, n / pk, pk); 
    for (ll i = 2; i <= n % pk; i++) 
        if (i % pi) res = res * i % pk; 
    return res * fac(n / pi, pi, pk) % pk; 
} 
ll inv(ll n, ll Mod) { 
    ll x, y;
    exgcd(n, Mod, x, y); 
    return (x + Mod) % Mod; 
} 
ll CRT(ll b, ll p, ll Mod) { return b * inv(p / Mod, Mod) % p * (p / Mod) % p; } 
ll C(ll n, ll m, ll pi, ll pk) { 
    ll fz = fac(n, pi, pk), fm1 = fac(m, pi, pk), fm2 = fac(n - m, pi, pk); 
    ll k = 0; 
    for (ll i = n; i; i /= pi) k += i / pi; 
    for (ll i = m; i; i /= pi) k -= i / pi; 
    for (ll i = n - m; i; i /= pi) k -= i / pi; 
    return fz * inv(fm1, pk) % pk * inv(fm2, pk) % pk * fpow(pi, k, pk) % pk; 
} 
ll exlucas(ll n, ll m, ll Mod) { 
    ll res = 0, tmp = Mod; 
    for (int i = 2; 1ll * i * i <= Mod; i++)
        if (tmp % i == 0) { 
            ll pk = 1; while (tmp % i == 0) pk *= i, tmp /= i; 
            res = (res + CRT(C(n, m, i, pk), Mod, pk)) % Mod; 
        } 
    if (tmp > 1) res = (res + CRT(C(n, m, tmp, tmp), Mod, tmp)) % Mod;
    return res; 
}
ll N, M, Mod;
ll sum, w[10];

int main () {
    cin >> Mod >> N >> M; 
    for (int i = 1; i <= M; i++) cin >> w[i], sum += w[i];
    if (N < sum) return puts("Impossible") & 0; 
    ll ans = 1; 
    for (int i = 1; i <= M; i++) { 
        ans = ans * exlucas(N, w[i], Mod) % Mod;
        N -= w[i]; 
    } 
    printf("%lld\n", ans); 
    return 0; 
}