BZOJ 2142 礼物(拓展Lucas,中国剩余定理)BZOJ修复工程
Posted 繁凡さん
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2142 礼物(拓展Lucas,中国剩余定理)BZOJ修复工程相关的知识,希望对你有一定的参考价值。
整理的算法模板合集: ACM模板
实际上是一个全新的精炼模板整合计划
题目链接
https://hydro.ac/d/bzoj/p/2142
是 hydro 的 BZOJ 修复工程 !(我也去领了一点题慢慢修着玩,这题就是我修的嘿嘿嘿)
题目描述
一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。不同的人物在小E心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多。小E从商店中购买了 n n n 件礼物,打算送给 m m m 个人,其中送给第 i i i 个人礼物数量为 w i w_i wi 。请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模 P P P 后的结果。
输入格式
输入的第一行包含一个正整数 P P P ,表示模数;
第二行包含两个整整数 n n n 和 m m m ,分别表示小E从商店购买的礼物数和接受礼物的人数;
以下 m m m 行每行仅包含一个正整数 w i w_i wi ,表示小E要送给第 i i i 个人的礼物数量。
输出格式
若不存在可行方案,则输出 “Impossible” ,否则输出一个整数,表示模 P P P 后的方案数。
输入样例
100
4 2
1
2
输出样例
12
数据规模和约定
设
P
=
p
1
c
1
×
p
2
c
2
×
p
3
c
3
×
⋯
×
p
t
c
t
P=p_1^{c_1} \\times p_2^{c_2} \\times p_3^{c_3} \\times \\cdots \\times p_t ^ {c_t}
P=p1c1×p2c2×p3c3×⋯×ptct,
p
i
p_i
pi 为质数。
对于
100
%
100\\%
100% 的数据,
1
≤
n
≤
1
0
9
1\\le n\\le 10^9
1≤n≤109,
1
≤
m
≤
5
1\\le m\\le 5
1≤m≤5,
1
≤
p
i
c
i
≤
1
0
5
1\\le p_i^{c_i}\\le 10^5
1≤pici≤105。
提示
【样例说明】
下面是对样例
1
1
1 的说明。
以 /
分割,/
前后分别表示送给第一个人和第二个人的礼物编号。
12
12
12 种方案详情如下:
1/23 1/24 1/34
2/13 2/14 2/34
3/12 3/14 3/24
4/12 4/13 4/23
Solution
一共 n n n 个礼物,第 1 1 1 个人需要 w 1 w_1 w1 个礼物,方案数为 ( w 1 n ) \\displaystyle {w_1 \\choose n} (nw1),然后对于第二个人,从剩下的 n − w 1 n-w_1 n−w1 个礼物中选出 w 2 w_2 w2 个礼物送给第二个人,方案数为 ( w 2 n − w 1 ) \\displaystyle {w_2\\choose {n-w_1}} (n−w1w2),一次类推,总方案数根据乘法原理显然为:
∏ i = 1 n ( w i n − ∑ j = 1 i w j ) m o d p \\prod_{i = 1}^{n} {w_i\\choose \\displaystyle n-\\sum_{j=1}^{i}w_j}\\mod p i=1∏n(n−j=1∑iwjwi)modp
考虑如何计算。
由于给定的模数 p p p 不是质数,所以我们需要用拓展Lucas定理计算,然后就是一个拓展lucas的模板题了…
关于拓展Lucas定理:
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 1e4 + 6;
int n, m, s, t, ans;
int primes[maxn], cnt;
bool vis[maxn];
int v[maxn], M;
ll A, B;
int mod;
int w[maxn];
int r[maxn];
struct mods
{
int c, p;
ll pc;
}f[maxn];
ll qpow(ll a, ll b, ll mod)
{
ll res = 1;
while(b) {
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if(b == 0) {
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, x, y);
ll z = x;
x = y;
y = z - y * (a / b);
return d;
}
inline ll inv(ll a, ll p)
{
ll x, y;
exgcd(a, p, x, y);
return (x + p) % p;
}
//计算 x! 中除掉 val = prime 后模 p 的值
inline ll cal(ll x, ll val, ll p)
{
if(x == 0) return 1;
ll res = 1;
ll last = x % p;
for (int i = 1; i <= p; ++ i)
if(i % val)
res = res * i % p;
res = qpow(res, x / p, p);
for (ll i = 1; i <= last; ++ i)
if(i % val)
res = res * i % p;
return res * cal(x / val, val, p) % p;
}
inline ll C(ll n, ll m, ll p, ll pc)
{
if(m > n) return 0;
ll k = 0;
ll up = cal(n, p, pc);
ll down1 = cal(m, p, pc);
ll down2 = cal(n - m, p, pc);
for (int i = n; i; i /= p) k += i / p;
for (int i = m; i; i /= p) k -= i / p;
for (int i = n - m; i; i /= p) k -= i / p;
return up * inv(down1, pc) % pc * inv(down2, pc) % pc * qpow(p, k, pc) % pc;
}
inline ll CRT(int cnt)
{
ll m = mod, M[maxn] = {}, t[maxn] = {}, res = 0;
for (int i = 1; i <= cnt; ++ i)
M[i] = m / f[i].pc;
for (int i = 1; i <= cnt; ++ i) {
ll y;
exgcd(M[i], f[i].pc, t[i], y);
res = (res + r[i] % m * M[i] % m * t[i] % m) % m;
}
return (res % m + m) % m;
}
inline ll exlucas(ll A, ll B)
{
memset(f, 0, sizeof f);
memset(r, 0, sizeof r);
int x = mod, cnt = 0;
for (ll i = 2; i * i <= x; ++ i) {
if(x % i == 0) {
f[ ++ cnt].p = i;
f[cnt].pc = 1;
while(x % i == 0) {
x /= i;
f[cnt].c ++ ;
f[cnt].pc *= i;
}
r[cnt] = C(A, B, f[cnt].p, f[cnt].pc);
}
}
if(x > 1) {
f[ ++ cnt].p = x;
f[cnt].c = 1;
f[cnt].pc = x;
r以上是关于BZOJ 2142 礼物(拓展Lucas,中国剩余定理)BZOJ修复工程的主要内容,如果未能解决你的问题,请参考以下文章