【BZOJ】2142 礼物
【算法】中国剩余定理
【题意】给定n件物品分给m个人,每人分到wi件,求方案数%p。p不一定是素数。
【题解】
首先考虑n全排列然后按wi划分成m份,然后对于每份内都是全排列,除以wi!消除标号影响,注意剩余的(n-W)也视为一份。
所以ans=n!/(w1!w2!...wm!(n-W)!)%p
也可以从排列组合公式方面考虑,即
ans=C(n,w1)*C(n-w1,w2)*C(n-w1-w2,w3)*...*C(n-w1-w2-...-w_(m-1),wm) mod P
=n!/w1!/w2!/.../wm!/(n-W)! mod P (by POPOQQQ)
ans=n!/(w1!w2!...wn!(n-W)!) %p
到这里已经转化为经典问题:非素数模数下,中国剩余定理求阶乘及阶乘逆元。
根据唯一分解定理,P=p1^c1*...*pk^ck,对于每个模数p^c分别求答案,最后用中国剩余定理合并。
因为模数底数p不充分大,所以要先在分子和分母处找因子p,上下约去然后用快速幂额外加入答案,剩余部分正常运算。
现在问题是从n!和(n!)^(-1)中分离出p,着重考虑从n!中分离出p,逆元照做。
fac(x)表示x!除去1~x中p的倍数后的结果,则有:
n!=fac(n)*[p^(n/p)]*(n/p)!
fac(n)为分离后的部分,[p^(n/p)]为分离出来的p,(n/p)!为分离出p后剩余的倍数。下面一一解决。
<fac(n)>
对于n!,因为取模p^c且已经分离p,所以阶乘数列以p^c为周期(p^c~2*p^c-1取模后就是0至p^c-1)
那么预处理fac[0~p^c-1](不乘p的倍数),fac(n)就是fac[n%pc]*{fac[p^c-1]^[n/(p^c)]}。
这部分答案为fac[n%pc]*power(fac[pc-1],n/pc) mod pc。
<[p^(n/p)]>累加进因子幂数,最后分子分母的因子幂数约去后用快速幂计算。
<(n/p)!>这部分又是阶乘,递归处理。
ll calc(ll x,ll p,ll pc)
{
if(x<p)return fac[x];
cnt+=x/p;
return fac[x%pc]*calc(x/p,p,pc)%pc*power(fac[pc-],x/pc,pc)%pc;
}
最后用中国剩余定理合并结果就可以了,注意ai是余数(即我们计算的结果),Mi是除pc[i]外的模数之积,ti是Mi的逆元,最后对M取模。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const ll maxn=;
ll p[maxn],pc[maxn],w[maxn],cnt,tot,fac[maxn],n,m,pp,M[maxn];
void gcd(ll a,ll b,ll &x,ll &y)
{
if(!b){x=;y=;}
else {gcd(b,a%b,y,x);y-=x*(a/b);}
}
ll get_inv(ll x,ll mods)
{
ll xx,yy;
gcd(x,mods,xx,yy);
return (((xx%mods)+mods)%mods);
}
ll power(ll x,ll k,ll mods)
{
ll ans=;
while(k>)
{
if(k&)ans=(ans*x)%mods;
x=(x*x)%mods;
k>>=;
}
return ans;
}
ll calc(ll x,ll p,ll pc)
{
if(x<p)return fac[x];
cnt+=x/p;
return fac[x%pc]*calc(x/p,p,pc)%pc*power(fac[pc-],x/pc,pc)%pc;//抄程序变量名错系列QAQ
}
ll left(ll p,ll pc)
{
fac[]=;
for(int i=;i<=pc-;i++)fac[i]=(fac[i-]*(i%p==?:i))%pc;
cnt=;
ll up=calc(n,p,pc);
ll upnum=cnt;
for(int i=;i<=pc-;i++)fac[i]=(fac[i-]*(i%p==?:get_inv(i,pc)))%pc;
cnt=;
ll down=;
for(int i=;i<=m;i++)down=(down*calc(w[i],p,pc))%pc;
ll downnum=cnt;
return up*down%pc*power(p,upnum-downnum,pc)%pc;
}
int main()
{
scanf("%lld%lld%lld",&pp,&n,&m);
ll sum=;
for(int i=;i<=m;i++){scanf("%lld",&w[i]);sum+=w[i];}
if(sum>n){printf("Impossible\n");return ;}
tot=;ll pop=pp;
for(ll i=;i*i<=pop;i++)
{
if(pop%i==)p[++tot]=i,pc[tot]=;
while(pop%i==)pc[tot]*=i,pop/=i;
}
if(pop>)p[++tot]=pop,pc[tot]=pop;
if(sum<n)w[++m]=n-sum;
for(int i=;i<=tot;i++)M[i]=pp/pc[i];
sum=;
for(int i=;i<=tot;i++)
{
sum=(sum+(left(p[i],pc[i])*get_inv(M[i],pc[i])%pp*M[i])%pp)%pp;//中国剩余定理合并时必须模M
}
printf("%lld",((sum%pp)+pp)%pp);
return ;
}
【BZOJ】2142 礼物的更多相关文章
- BZOJ 2142: 礼物 [Lucas定理]
		
2142: 礼物 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1294 Solved: 534[Submit][Status][Discuss] ...
 - BZOJ 2142 礼物 组合数学 CRT 中国剩余定理
		
2142: 礼物 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1450 Solved: 593[Submit][Status][Discuss] ...
 - 【刷题】BZOJ 2142 礼物
		
Description 一年一度的圣诞节快要来到了.每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物.不同的人物在小E 心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多.小E从商店 ...
 - bzoj 2142 礼物——扩展lucas模板
		
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2142 没给P的范围,但说 pi ^ ci<=1e5,一看就是扩展lucas. 学习材料 ...
 - bzoj 2142: 礼物【中国剩余定理+组合数学】
		
参考:http://blog.csdn.net/wzq_qwq/article/details/46709471 首先推组合数,设sum为每个人礼物数的和,那么答案为 \[ ( C_{n}^{sum} ...
 - BZOJ 2142: 礼物
		
模非素数下的排列组合,简直凶残 调着调着就过了= = 都不知道怎么过的= = 直接上链接http://hi.baidu.com/aekdycoin/blog/item/147620832b567eb4 ...
 - BZOJ.2142.礼物(扩展Lucas)
		
题目链接 答案就是C(n,m1) * C(n-m1,m2) * C(n-m1-m2,m3)...(mod p) 使用扩展Lucas求解. 一个很简单的优化就是把pi,pi^ki次方存下来,因为每次分解 ...
 - BZOJ - 2142 礼物 (扩展Lucas定理)
		
扩展Lucas定理模板题(貌似这玩意也只能出模板题了吧~~本菜鸡见识鄙薄,有待指正) 原理: https://blog.csdn.net/hqddm1253679098/article/details ...
 - BZOJ 2142 礼物 数论
		
这道题是求组合数终极版. C(n,m) mod P n>=1e9 m>=1e9 P>=1e9且为合数且piqi<=1e5 拓展lucas定理. 实际上就是一点数论小知识的应用. ...
 - bzoj 3055礼物运送 floyed + 状压DP
		
bzoj 3055: 礼物运送 floyed first 设f[i][S]表示取到了S集合中的所有点(不一定是经过的所有点),最后停在了i的最优值. 初始就f[i][{i}] = dis[1][i] ...
 
随机推荐
- Java中的网络编程-1
			
计算机网络:将分布在不同地区的计算机与专门的外部设备用通信线路互连成一个规模大.功能强的网络系统, 从而使众多计算机 可以方便的互相传递信息, 共享硬件.软件.数据信息等资源. 计算机网络的主要功能: ...
 - CoordinatdBolt原理分析
			
参考链接:http://xumingming.sinaapp.com/811/twitter-storm-code-analysis-coordinated-bolt/ CoordinatedBolt ...
 - Struts2(五)
			
以下内容是基于导入struts2-2.3.32.jar包来讲的 1.文件上传 A.单文件上传 <body> <form action="${pageContext.requ ...
 - String、StringBuilder与StringBuffer的区别
			
1.String类是public.final修饰的. 在Java中,被final修饰的类是不允许被继承的,并且String它的成员方法都默认为final方法. 查看源码得知,String类其实是通过c ...
 - CCF——折点计数201604-1
			
问题描述 给定n个整数表示一个商店连续n天的销售量.如果某天之前销售量在增长,而后一天销售量减少,则称这一天为折点,反过来如果之前销售量减少而后一天销售量增长,也称这一天为折点.其他的天都不是折点.如 ...
 - ci事务
			
CI框架百问百答:CodeIgniter的事务用法?--第9问 时间 2013-06-06 10:57:45 CSDN博客 原文 http://blog.csdn.net/haor2756/art ...
 - MySQL 事务 转自菜鸟教程 讲的清晰
			
MySQL 事务 MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数 ...
 - [cnbeta]微软最强数据中心级操作系统
			
微软近日发表了一篇介绍Windows系统内核的博文,期间为了展示Windows的强大扩展性,放出了一张非常震撼的Windows任务管理器截图:乍一看似乎没啥特别的,几十甚至上百个逻辑核心的系统并不罕见 ...
 - 【转】Linux C 网络编程——TCP套接口编程
			
地址:http://blog.csdn.net/matrix_laboratory/article/details/13669211 2. socket() <span style=" ...
 - Linux 常用指令【持续更新】
			
在学校的时候学过一些简单的 Linux 命令,主要是文件的创建拷贝解压等操作,最近在电脑上安装了一个CentOS6.8版本的基本版,纯命令行操作. ../ 代表上一级目录 ./ 代表本级目录 / 代表 ...