洛谷 P2183 [国家集训队]礼物
题目描述
一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。不同的人物在小E心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多。小E从商店中购买了n件礼物,打算送给m个人,其中送给第i个人礼物数量为wi。请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模P后的结果。
输入输出格式
输入格式:
输入的第一行包含一个正整数P,表示模;
第二行包含两个整整数n和m,分别表示小E从商店购买的礼物数和接受礼物的人数;
以下m行每行仅包含一个正整数wi,表示小E要送给第i个人的礼物数量。
输出格式:
若不存在可行方案,则输出“Impossible”,否则输出一个整数,表示模P后的方案数。
输入输出样例
100
4 2
1
2
12
100
2 2
1
2
Impossible
说明
【样例说明】
下面是对样例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为质数。
对于15%的数据,n≤15,m≤5,pi^ci≤10^5;
在剩下的85%数据中,约有60%的数据满足t≤2,ci=1,pi≤10^5,约有30%的数据满足pi≤200。
对于100%的数据,1≤n≤10^9,1≤m≤5,1≤pi^ci≤10^5,1≤P≤10^9。
这个很好想啦,就是模数不是质数会很麻烦。
没错,这就是一道扩展卢卡斯+中国剩余定理的模板题。
大致的做法就是先把P质因数分解,然后得到在每个质因数^次数下的答案,最后用中国剩余定理合并。。
那么现在问题的关键变成了如何求n! mod p^k。
这个可以拆成三部分(准确的说是最多三部分),
1:n!中是p倍数的可以直接拆出来,递归求(n/p)! mod p^k。
2.n!中可能有很多个完整的1~p^k-1,这部分可以先预处理一下(p^k-1)! (当然是不算p的倍数的阶乘,因为我们还要记录一下阶乘中p的次数最后一起处理),然后快速幂一下。
3.n%(p^k)的部分可以直接乘预处理的了。
可能第一次写会比较费劲,,,,
(还有我为什么忘了中国剩余定理了23333,记住是∑a[i]*(P/mod[i])*inv(P/mod[i],mod[i]))
#include<bits/stdc++.h>
#define ll long long
#define maxn 100005
using namespace std;
int N,P,m,a[15],MOD;
int d[15],c[15],mo;
int D[15],jc[maxn];
int num,ans[15],tot; inline int add(int x,int y,const int ha){
x+=y;
if(x>=ha) return x-ha;
else return x;
} inline int ksm(int x,int y,const int ha){
int an=1;
for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
return an;
} struct node{
int val,tmp;
node operator *(const node &U)const{
return (node){val*(ll)U.val%D[mo],tmp+U.tmp};
}
node operator /(const node &U)const{
return (node){val*(ll)ksm(U.val,D[mo]/d[mo]*(d[mo]-1)-1,D[mo])%D[mo],tmp-U.tmp};
}
}; inline void dvd(){
for(int i=2;i*(ll)i<=P;i++) if(!(P%i)){
d[++num]=i,D[num]=1;
while(!(P%i)) P/=i,D[num]*=i,c[num]++;
if(P==1) break;
}
if(P!=1) d[++num]=D[num]=P,c[num]=1;
} inline node getjc(int x){
node now=(node){1,0};
if(x>=d[mo]) now=now*getjc(x/d[mo]),now.tmp+=x/d[mo]; if(x>=D[mo]) now=now*(node){ksm(jc[D[mo]-1],x/D[mo],D[mo]),0}; now=now*(node){jc[x%D[mo]],0};
return now;
} inline node getC(int x,int y){
return getjc(x)/getjc(y)/getjc(x-y);
} inline void solve(int x){
jc[0]=1,mo=x;
for(int i=1;i<D[x];i++){
jc[i]=jc[i-1];
if(i%d[x]) jc[i]=jc[i]*(ll)i%D[x];
} ans[x]=1;
int lef=N;
node now;
for(int i=1;i<=m;i++){
now=getC(lef,a[i]);
// printf("%d %d %d %d\n",lef,a[i],now.val,now.tmp);
ans[x]=ans[x]*(ll)now.val%D[x]*(ll)ksm(d[x],now.tmp,D[x])%D[x];
lef-=a[i];
}
} inline int CRT(){
int an=0;
for(int i=1;i<=num;i++){
an=add(an,ksm(MOD/D[i],D[i]/d[i]*(d[i]-1)-1,D[i])*(ll)(MOD/D[i])%MOD*(ll)ans[i]%MOD,MOD);
}
return an;
} int main(){
scanf("%d%d%d",&P,&N,&m),MOD=P;
for(int i=1;i<=m;i++) scanf("%d",a+i),tot+=a[i]; if(tot>N){
puts("Impossible");
return 0;
} dvd(); for(int i=1;i<=num;i++) solve(i); printf("%d\n",CRT());
return 0;
}
洛谷 P2183 [国家集训队]礼物的更多相关文章
- 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)
洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ...
- [洛谷P1527] [国家集训队]矩阵乘法
洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ...
- 洛谷P1501 [国家集训队]Tree II(LCT,Splay)
洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...
- 洛谷P2619 [国家集训队2]Tree I(带权二分,Kruscal,归并排序)
洛谷题目传送门 给一个比较有逼格的名词--WQS二分/带权二分/DP凸优化(当然这题不是DP). 用来解决一种特定类型的问题: 有\(n\)个物品,选择每一个都会有相应的权值,需要求出强制选\(nee ...
- 洛谷 P1407 [国家集训队]稳定婚姻 解题报告
P1407 [国家集训队]稳定婚姻 题目描述 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的 ...
- 洛谷 P1852 [国家集训队]跳跳棋 解题报告
P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...
- 洛谷 P1501 [国家集训队]Tree II 解题报告
P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...
- 洛谷 P2757 [国家集训队]等差子序列 解题报告
P2757 [国家集训队]等差子序列 题目描述 给一个\(1\)到\(N\)的排列\(\{A_i\}\),询问是否存在 \[1 \le p_1<p_2<p_3<p_4<p_5& ...
- 洛谷 P1505 [国家集训队]旅游 解题报告
P1505 [国家集训队]旅游 题目描述 \(\tt{Ray}\) 乐忠于旅游,这次他来到了\(T\)城.\(T\)城是一个水上城市,一共有 \(N\) 个景点,有些景点之间会用一座桥连接.为了方便游 ...
随机推荐
- day06_08 字符串
1.0 双引号和单引号的区别 a = "Let's go" print(a) #>>>Let's go 2.0 重复输出字符串* print('hello'*2) ...
- cinatra--一个高效易用的c++ http框架
cinatra是一个高性能易用的http框架,它是用modern c++(c++17)开发的,它的目标是提供一个快速开发的c++ http框架.它的主要特点如下: 统一而简单的接口 header-on ...
- ocrosoft Contest1316 - 信奥编程之路~~~~~第三关 问题 K: 大整数加法
http://acm.ocrosoft.com/problem.php?cid=1316&pid=10 题目描述 求两个不超过200位的非负整数的和. 输入 有两行,每行是一个不超过200 ...
- free、vmstat监视内存使用情况
9. free 查询可用内存 free工具用来查看系统可用内存: /opt/app/tdev1$free total used free shared buffers cached Mem: 8175 ...
- 【转】Thinkphp框架的项目规划总结和踩坑经验
http://www.360doc.com/content/16/1206/22/466494_612576533.shtml
- lua中如何识别C语言中的struct
不如用c写比较简单呢 都要在lua中解析好数据结构,不过也可以用ffi呢...proto.lua
- 动态MST
原谅我真的写不下去了,太难写了,先占坑. 啥时候有比较连续的时间了再写 肯定没用了的无聊代码 #include <cstdio> #include <vector> const ...
- How to secure remote desktop connections using TLS/SSL
How to secure remote desktop connections using TLS/SSL based authentication Requirement When you ena ...
- ajax数据读取和绑定
如何进行ajax数据读取和绑定呢? 首先创建一个AJAX对象 实现数据绑定 实现隔行变色 编写表格排序的方法(实现按照年龄这一列进行排序) 通过文档碎片,把排序后的最新顺序,重新添加到tBody中(通 ...
- nutch 2.1安装问题集锦
参照官方文档http://nlp.solutions.asia/?p=180 中间碰到的问题,解决方法参考 http://blog.javachen.com/2014/05/20/nutch-intr ...