【LG2183】[國家集訓隊]禮物
阿新 • • 發佈:2019-01-02
【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; }