[xsy2880]取石子游戏
题意:有$n$堆石子,每堆石子数量相同,以质因数分解给出,不停地从$1$到$n$依次拿石子,使得取完后石子个数为原来的因数(不能不取),当一堆只剩$1$个时结束,问在每堆石子结束的方案数
记石子个数为$\prod\limits_{i=1}^mp_i^{e_i}$,拿石头就是选一些$e_i$把它们减小
令一堆石子取$x$次取完的方案数为$f_x$,取$x-1$次还未取完的方案数为$g_x$,那么$g_x=f_x$,因为对于每个取$x-1$次未取完的方案,把它取完就对应一个$x$次取完的方案,对于每个$x$次取完的方案,它的前$x-1$次操作一定不完全相同,所以两种方案数相同
记$s=\sum e_i$,那么取$j$次取完并在$i$结束的方案数为$g_{j+1}^{i-1}f_jg_j^{n-i}=f_{j+1}^{i-1}f_j^{n-i+1}$,所以答案为$ans_i=\sum\limits_{j=1}^sf_{j+1}^{i-1}f_j^{n-i+1}$
现在我们来算$f$,直接算将$e_i$分成$x$份的方案数就是$h_x=\prod\limits_{i=1}^m\binom{e_i+x-1}{x-1}$,但$h_x\ne f_x$,因为$h_x$中可能包含那些某一次一个石子都没取的方案,所以要容斥
取$x$次中,至少有$y$次一个石子都没取的方案数为$\binom xyh_{x-y}$,那么$f_x=\sum\limits_{y=0}^x(-1)^y\binom xyh_{x-y}$,也就是说求出$h$后我们就可以$O(s\log s)$求$f$了
原题中$h$可以暴力求,但毒瘤代爷稍微加强了一下数据,注意到因为$\sum e_i=s$,所以不同的$e_i$最多会有$O(\sqrt s)$个,所以我们对相同的$e_i$一起处理,就可以在$O(s\sqrt s\log s)$的时间内递推求得$h$
总时间复杂度$O(s\sqrt s\log s)$
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=998244353;
int mul(int a,int b){return(ll)a*b%mod;}
int ad(int a,int b){return(a+b)%mod;}
int de(int a,int b){return(a-b)%mod;}
void inc(int&a,int b){(a+=b)%=mod;}
int pow(int a,int b){
int s=1;
while(b){
if(b&1)s=mul(s,a);
a=mul(a,a);
b>>=1;
}
return s;
}
int rev[1048576],N,iN;
void pre(int n){
int i,k=0;
for(N=1,k=0;N<=n;N<<=1)k++;
for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
iN=pow(N,mod-2);
}
void ntt(int*a,int on){
int i,j,k,t,w,wn;
for(i=0;i<N;i++){
if(i<rev[i])swap(a[i],a[rev[i]]);
}
for(i=2;i<=N;i<<=1){
wn=pow(3,on==1?(mod-1)/i:mod-1-(mod-1)/i);
for(j=0;j<N;j+=i){
w=1;
for(k=0;k<i>>1;k++){
t=mul(a[i/2+j+k],w);
a[i/2+j+k]=de(a[j+k],t);
a[j+k]=ad(a[j+k],t);
w=mul(w,wn);
}
}
}
if(on==-1){
for(i=0;i<N;i++)a[i]=mul(a[i],iN);
}
}
int e[10010],inv[300010],fac[300010],rfac[300010],h[300010],f[300010],c[300010],pe[300010],pc[300010];
int C(int n,int k){return mul(fac[n],mul(rfac[k],rfac[n-k]));}
int a[1048576],b[1048576];
int main(){
int m,n,s,i,j,t,M;
scanf("%d%d",&m,&n);
s=0;
for(i=1;i<=m;i++){
scanf("%d%d",&t,e+i);
s+=e[i];
c[e[i]]++;
}
M=0;
for(i=1;i<=s;i++){
if(c[i]){
M++;
pe[M]=i;
pc[M]=c[i];
}
}
fac[0]=1;
for(i=1;i<=s;i++)fac[i]=mul(fac[i-1],i);
rfac[s]=pow(fac[s],mod-2);
for(i=s;i>0;i--)rfac[i-1]=mul(rfac[i],i);
inv[1]=1;
for(i=2;i<=s;i++)inv[i]=-mul(mod/i,inv[mod%i]);
h[1]=1;
for(i=1;i<s;i++){
h[i+1]=h[i];
for(j=1;j<=M;j++)h[i+1]=mul(h[i+1],pow(mul(pe[j]+i,inv[i]),pc[j]));
}
pre(s<<1);
for(i=0;i<=s;i++){
a[i]=(i&1?-1:1)*rfac[i];
b[i]=mul(h[i],rfac[i]);
}
ntt(a,1);
ntt(b,1);
for(i=0;i<N;i++)a[i]=mul(a[i],b[i]);
ntt(a,-1);
for(i=0;i<=s;i++)f[i]=mul(a[i],fac[i]);
for(i=1;i<=n;i++){
t=0;
for(j=1;j<=s;j++)inc(t,mul(pow(f[j+1],i-1),pow(f[j],n-i+1)));
inc(t,mod);
printf("%d\n",t);
}
}
[xsy2880]取石子游戏的更多相关文章
- Games:取石子游戏(POJ 1067)
取石子游戏 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 37662 Accepted: 12594 Descripti ...
- HDU 2516 取石子游戏(斐波那契博弈)
取石子游戏 Time Limit: 2000/1000 MS(Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...
- hdu 1527 取石子游戏(Wythoff Game)
题意:Wythoff Game 思路:Wythoff Game #include<iostream> #include<stdio.h> #include<math.h& ...
- HDU 2516 取石子游戏(FIB博弈)
取石子游戏 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- 1874: [BeiJing2009 WinterCamp]取石子游戏 - BZOJ
Description小H和小Z正在玩一个取石子游戏. 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子,每次取石子的个数有限制,谁不能取石子时就会输掉游戏. 小H先进行操作,他想问 ...
- HDU-1527 取石子游戏
http://acm.hdu.edu.cn/showproblem.php?pid=1527 交换 :可实现. if( n < m ) { n^=m; m^=n; n^=m; } (三)尼姆博 ...
- bzoj 1874 取石子游戏 题解 & SG函数初探
[原题] 1874: [BeiJing2009 WinterCamp]取石子游戏 Time Limit: 5 Sec Memory Limit: 162 MB Submit: 334 Solved ...
- HDU 2516 取石子游戏 (博弈论)
取石子游戏 Problem Description 1堆石子有n个,两人轮流取.先取者第1次能够取随意多个,但不能所有取完.以后每次取的石子数不能超过上次取子数的2倍.取完者胜.先取者负输出" ...
- 【POJ】1067 取石子游戏(博弈论)
Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后 ...
随机推荐
- Windows下基于python3使用word2vec训练中文维基百科语料(三)
对前两篇获取到的词向量模型进行使用: 代码如下: import gensim model = gensim.models.Word2Vec.load('wiki.zh.text.model') fla ...
- 自定义ToolBar
一.Toolbar的简介 Toolbar 是 android 5.0 引入的一个新控件,Toolbar出现之前,我们很多时候都是使用ActionBar以及ActionActivity实现顶部导航栏的, ...
- Android控件——监听按钮的点击事件
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAroAAAFTCAIAAABZPDiZAAAgAElEQVR4nOy9918UWfb///1jdu2uBs
- 9.quartus_warning_altera_reserved_tck
编译的时候没有注意,整个工程都可以在板子上跑起来.但是做Powerplay的时候,出现了这个Critical Warning:. Critical Warning: The following clo ...
- io多路复用-select()
参照<Unix网络编程>相关章节内容,实现了一个简单的单线程IO多路复用服务器与客户端. 普通迭代服务器,由于执行recvfrom则会发生阻塞,直到客户端发送数据并正确接收后才能够返回,一 ...
- 网络设备之pci_driver
每个pci驱动都有一个pci_driver实例,用以描述驱动名称,支持的设备信息,以及对应的操作函数: /* 描述一个pci设备,每个pci驱动必须创建一个pci_driver实例 */ struct ...
- 64_g2
gettext-libs-0.19.8.1-9.fc26.x86_64.rpm 15-Mar-2017 14:15 305038 gf2x-1.1-9.fc26.i686.rpm 11-Feb-201 ...
- 【bzoj1072】SCOI2007排列
状压dp,f[i][j]表示当前取了i,模数余j的状态. 然后向后推,枚举可能的数即可. 注意每个数存在重复,最后要除以相应出现次数的阶乘. #include<bits/stdc++.h> ...
- springboot基础知识学习
一.springboot中常用的注解: 原文链接:http://blog.csdn.net/lafengwnagzi/article/details/53034369 原文链接:http://www. ...
- Redis -- 数据类型小结
redis key 的命名规则: 对象类型:对象id:对象属性 (hset car:1: price 500.hset car:1: name:tom) 一.redis 数据类型: 1. 字符串类型 ...