【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
", ans); 
	return 0; 
} 
原文地址:https://www.cnblogs.com/heyujun/p/10207226.html