卧薪尝胆,厚积薄发。
国家集训队 礼物
Date: Mon Jul 02 19:55:18 CST 2018 In Category: NoCategory

Description:

$n$ 个礼物分给 $m$ 个人,第 $i$ 个人分得 $w_i$ 个,问方案数。 $1\le N \le 10^9$ 模数不为质数。

Solution:

答案为: $C_n^{w_1}\times C_{n-w_1}^{w_2}\times\dots\times C_{n-\sum wi}^{w_m}$
用扩展卢卡斯定理求出来即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
ll MOD;
ll m,n;
#define MAXN 6
ll w[MAXN];
ll tot = 0,divi[100000],times[100000];
ll sumw = 0;
void dev()
{
ll k = MOD;
for(ll i = 2;i <= k;++i)
{
if(k % i == 0)
{
divi[++tot] = i;
times[tot] = 1;
while(k % i == 0)
{
times[tot] *= i;
k /= i;
}
}
}
return;
}
ll power(ll a,ll b,ll mod)//a ^ b % mod
{
ll res = 1;
while(b > 0)
{
if(b & 1)res = res * a % mod;
a = a * a % mod;
b = b >> 1;
}
return res;
}
ll fac(ll n,ll p,ll pr)//n! % pr
{
if(n == 0)return 1;
ll res = 1;
for(ll i = 2;i <= pr;++i)
{
if(i % p != 0)
{
res = res * i % pr;
}
}
res = power(res,n / pr,pr);
ll r = n % pr;
for(ll i = 2;i <= r;++i)
{
if(i % p != 0)
{
res = res * i % pr;
}
}
res = res * fac(n / p,p,pr) % pr;
return res;
}
ll exgcd(ll a,ll b,ll &x,ll &y)//ax + by = gcd(a,b)
{
if(b == 0)
{
x = 1;y = 0;
return a;
}
ll t = exgcd(b,a % b,x,y);
ll k = x;
x = y;
y = k - (a / b) * y;
return t;
}
ll inv(ll a,ll n)//a * a^{-1} = 1 (mod n)
{
ll x,y;
ll t = exgcd(a,n,x,y);
x = (x % n + n) % n;
return x;
}
ll lucas(ll n,ll m,ll p,ll pr)
{
if(n < m)return 0;
ll c = 0;
for(ll i = n;i > 0;i /= p)c += i / p;
for(ll i = m;i > 0;i /= p)c -= i / p;
for(ll i = n - m;i > 0;i /= p)c -= i / p;
ll res = fac(n,p,pr) * inv(fac(m,p,pr),pr) % pr * inv(fac(n - m,p,pr),pr) % pr * power(p,c,pr) % pr;
return res;
}
ll CRT(ll n,ll m)
{
ll ans = 0;
for(int i = 1;i <= tot;++i)
{
ans = (ans + lucas(n,m,divi[i],times[i]) * inv(MOD / times[i],times[i]) % MOD * (MOD / times[i]) % MOD) % MOD;
}
return ans;
}
int main()
{
scanf("%lld",&MOD);
scanf("%lld%lld",&m,&n);
for(int i = 1;i <= n;++i)
{
scanf("%lld",&w[i]);
sumw += w[i];
}
if(sumw > m){puts("Impossible");return 0;}
if(MOD == 1){puts("0");return 0;}
dev();
ll ans = 1;
for(int i = 1;i <= n;++i)
{
ans = ans * CRT(m,w[i]) % MOD;
m -= w[i];
}
cout << ans << endl;
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡