【BZOJ2142】礼物

Description

小E从商店中购买了n件礼物,打算送给m个人,其中送给第i个人礼物数量为wi。请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模P后的结果。

Input

输入的第一行包含一个正整数P,表示模;
第二行包含两个整整数n和m,分别表示小E从商店购买的礼物数和接受礼物的人数;
以下m行每行仅包含一个正整数wi,表示小E要送给第i个人的礼物数量。

Output

若不存在可行方案,则输出“Impossible”,否则输出一个整数,表示模P后的方案数。

Sample Input

100
4 2
1
2

Sample Output

12
【样例说明】
下面是对样例1的说明。
以“/”分割,“/”前后分别表示送给第一个人和第二个人的礼物编号。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
【数据规模和约定】
设P=p1^c1 * p2^c2 * p3^c3 * … *pt ^ ct,pi为质数。
对于100%的数据,1≤n≤109,1≤m≤5,1≤pi^ci≤10^5。

题解:答案很简单,$ans=C_{tot}^{w1}C_{tot-w1}^{w2}C_{tot-w1-w2}^{w3}...$。

但是问题来了,首先模数既不是质数,也不是若干独立质数的乘积,而是质数的幂次之积。我们还是先用中国剩余定理,将模数变成质数的幂次,但此时普通的lucas定理无法使用,我们怎么求组合数呢?

我们考虑将组合数变成阶乘相除的形式,再将分子和分母中的阶乘都化成$a\times p^b$的形式(a对$p^c$取模),最后答案的a等于分子的a乘上分母的a的逆元,答案的b等于分子的b-分母的b。那么我们考虑如何将一个数的阶乘化成$a\times p^b$的形式。

以$p=5,p^c=25$为例,然后将n的阶乘中5的倍数都提出来考虑:

$n!=(1\times2\times3\times4\times6\times7\times...)\times5^{\lfloor\frac n 5\rfloor}\times(\lfloor\frac n 5\rfloor)!$

那么如何处理前面的那坨东西呢?我们可以先预处理出$1...24$的阶乘(不计算p的倍数),即为jc,然后前面的那堆东西就变成了$jc[24]^{\lfloor \frac n {25}\rfloor}\times jc[n\%25]$。

对于后面的那个阶乘,我们可以递归处理下去,每次n的大小会除以p,所以复杂度是可以接受的~

最后用CRT合并,求逆元时用exgcd即可,注意判Impossible的情况。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=100010;
ll n,m,num,P,PP,PC,Pri,ans;
ll w[10],jc[maxn];
inline ll pm(ll x,ll y)
{
ll ret=1;
while(y)
{
if(y&1) ret=ret*x%PP;
x=x*x%PP,y>>=1;
}
return ret;
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1,y=0;
return ;
}
exgcd(b,a%b,x,y);
ll t=x;
x=y,y=t-a/b*x;
}
inline ll ine(ll a)
{
ll x,y;
exgcd(a,PP,x,y);
return x;
}
struct node
{
ll x,y;
node() {x=1,y=0;}
node(ll a,ll b) {x=a,y=b;}
node operator + (const node &a) const {return node(x*a.x%PP,y+a.y);}
node operator * (const ll &a) const {return node(pm(x,a),y*a);}
node operator - (const node &a) const {return node(x*(ine(a.x)+PP)%PP,y-a.y);}
};
inline node getjc(ll x)
{
if(x<P) return node(jc[x],0);
return node(pm(jc[PP-1],x/PP)*jc[x%PP]%PP,x/P)+getjc(x/P);
}
inline ll solve()
{
ll i,sum=n;
for(jc[0]=1,i=1;i<PP;i++)
{
jc[i]=jc[i-1];
if(i%P) jc[i]=jc[i]*i%PP;
}
node a,b;
for(i=1;i<=m;i++) b=b+getjc(w[i]),sum-=w[i];
a=getjc(n),b=b+getjc(sum);
a=a-b;
return a.x*pm(P,a.y);
}
inline ll CRT()
{
ll i,t=Pri;
for(i=2;i*i<=t;i++)
{
if(t%i==0)
{
P=i,PP=1,PC=0;
while(t%i==0) t/=i,PP*=i,PC++;
ans=(ans+ine(Pri/PP)*solve()*(Pri/PP))%Pri;
}
}
if(t!=1)
{
P=PP=t,PC=1;
ans=(ans+ine(Pri/PP)*solve()*(Pri/PP))%Pri;
}
return (ans+Pri)%Pri;
}
int main()
{
scanf("%lld%lld%lld",&Pri,&n,&m);
ll tmp=0;
for(ll i=1;i<=m;i++) scanf("%lld",&w[i]),tmp+=w[i];
if(tmp>n)
{
printf("Impossible");
return 0;
}
printf("%lld",CRT());
return 0;
}

【BZOJ2142】礼物 组合数+CRT的更多相关文章

  1. BZOJ 2142 礼物 组合数学 CRT 中国剩余定理

    2142: 礼物 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1450  Solved: 593[Submit][Status][Discuss] ...

  2. [BZOJ2142]礼物(扩展Lucas)

    2142: 礼物 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2286  Solved: 1009[Submit][Status][Discuss] ...

  3. [bzoj2142]礼物(扩展lucas定理+中国剩余定理)

    题意:n件礼物,送给m个人,每人的礼物数确定,求方案数. 解题关键:由于模数不是质数,所以由唯一分解定理, $\bmod  = p_1^{{k_1}}p_2^{{k_2}}......p_s^{{k_ ...

  4. BZOJ2142: 礼物(拓展lucas)

    Description 一年一度的圣诞节快要来到了.每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物.不同的人物在小E 心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多.小E从商店 ...

  5. BZOJ2142礼物——扩展卢卡斯

    题目描述 一年一度的圣诞节快要来到了.每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物.不同的人物在小E 心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多.小E从商店中购买了n件礼 ...

  6. BZOJ2142 礼物 扩展lucas 快速幂 数论

    原文链接http://www.cnblogs.com/zhouzhendong/p/8110015.html 题目传送门 - BZOJ2142 题意概括 小E购买了n件礼物,送给m个人,送给第i个人礼 ...

  7. bzoj2142 礼物——扩展卢卡斯定理

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2142 前几天学了扩展卢卡斯定理,今天来磕模板! 这道题式子挺好推的(连我都自己推出来了) , ...

  8. HZOI20190722 B visit 组合数+CRT合并

    题目:https://www.cnblogs.com/Juve/articles/11226266.html solution: 30%:dp 设dp[k][i][j]表示经过k时间,在(i,j)的方 ...

  9. bzoj2142: 礼物

    2142: 礼物 Description 一年一度的圣诞节快要来到了.每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物.不同的人物在小E心目中的重要性不同,在小E心中分量越重的人,收到的礼物会 ...

随机推荐

  1. iOS开发中的错误整理,导航控制器的导航栏取消系统渲染的错误

  2. java判断邮件是否发送成功

    http://www.cnblogs.com/winner-0715/p/5136392.html

  3. 实现整数转化为字符串函数itoa()函数

    函数原型: char *itoa( int value, char *string,int radix);原型说明:value:欲转换的数据.string:目标字符串的地址.radix:转换后的进制数 ...

  4. 符号arg含义

    argument of the maximum/minimum arg max f(x): 当f(x)取最大值时,x的取值 arg min f(x):当f(x)取最小值时,x的取值 表示使目标函数取最 ...

  5. Linux 精确获取指定目录对应的块的剩余空间

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/statfs ...

  6. 修改MySQL的默认密码的四种小方法

    投稿:lijiao 字体:[增加 减小] 类型:转载 时间:2015-09-05我要评论 对于windows平台来说安装完MySQL后,系统就已经默认生成了许可表和账户,下文中就教给大家如何修改MyS ...

  7. (转)如何根据RGB值来判断这是种什么颜色?

    如何根据RGB值来判断这是种什么颜色? 下面介绍几种典型颜色的RGB值,格式为:颜色(R,G,B). 想象一下有红.绿.蓝三盏射灯打出三束光. 这三束光叠加在一起时产生白色,如果三盏灯的亮度都减半就产 ...

  8. SVN版本冲突,导致出现Files 的值“ < < < < < < < .mine”无效。路径中具有非法字符。

    SVN版本冲突,导致出现Files 的值“ < < < < < < < .mine”无效.路径中具有非法字符. 右键编辑.... 打开并删除含有'<&l ...

  9. mysql压缩包的安装、配置、配成windows服务、远程连接及常规问题

    1.下载windows安装包 下载地址:mysql-5.7.18 2.配置my.ini [client] port = 3306 # 设置mysql客户端连接服务端时默认使用的端口 [mysql] d ...

  10. PHP实现金额数字转换成大写函数

    <?php header("Content-Type:text/html;charset=utf-8"); function num_to_upper($num) { $d ...