[Contest20180426]校门外的树
$\newcommand{\align}[1]{\begin{align*}#1\end{align*}}$题意:对于一个排列$p_{1\cdots n}$构造一个图,如果$i\lt j$且$p_i\lt p_j$,就连双向边$(i,j)$,这个排列的权值就是所有连通块的大小的乘积,求所有$n!$个排列的权值总和
考虑DP,设$f_n$表示(长度为$n$的排列构成的图)连通的方案数,则我们可以用$n!$减去不连通的方案数,考虑把不合法的方案按第一个连通块大小$i$分类,则后$n-i$个数可以随意乱排,所以$\align{f_n=n!-\sum\limits_{i=1}^{n-1}(n-i)!f_i}$
设答案为$g_n$,枚举最后一个连通块的大小$i$,我们得到转移$\align{g_n=\sum\limits_{i=1}^nif_ig_{n-i}}$
这样做是$O(n^2)$的,考虑优化
先转化一下$f$的递推式,$\align{2n!=[n=0]+\sum\limits_{i=0}^n(n-i)!f_i}$
设$\align{A(x)=\sum\limits_ii!x^i,B(x)=\sum\limits_if_ix^i}$,则$2A(x)=A(x)B(x)+1$,即$B(x)=\dfrac{2A(x)-1}{A(x)}$
直接多项式求逆可以算出$B(x)$,设$\align{C(x)=\sum\limits_iif_ix^i}$,现在考虑算答案,枚举答案中连通块的个数$k$,答案为$\align{[x^n]\sum\limits_{i=1}^\infty C^k(x)=[x^n]\left(\dfrac1{1-C(x)}-1\right)}$,算出$C(x)$再求逆就可以了
但是毒瘤yww把它出到$n\leq5\times10^5$,这样做如果写的丑会T掉,所以我们来卡卡常==
首先注意到$C(x)$其实就是$B(x)$的每一项系数多了一个$i$,所以$C(x)=xB'(x)$,再利用$B(x)=\dfrac{2A(x)-1}{A(x)}$,我们得到$\dfrac1{1-C(x)}=\dfrac{A^2(x)}{A^2(x)-xA'(x)}$,优化到了只用两次FFT和一次多项式求逆,已经可以过了
还可以继续优化,我们需要找到快速计算$\align{h_n=[x^n]A^2(x)=\sum\limits_{i=0}^ni!(n-i)!}$的方法,在OEIS上可以找到递推公式$h_n=n!+\dfrac{n+1}2h_{n-1}$,但我并没有找到证明,看看以后有没有机会填坑,这样做就可以只做一次多项式求逆
#include<stdio.h> #include<string.h> const int mod=998244353,maxn=1048576; typedef long long ll; int mul(int a,int b){return a*(ll)b%mod;} int ad(int a,int b){return(a+b)%mod;} int de(int a,int b){return(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[maxn],N,iN; void pre(int n){ int i,k; 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 swap(int&a,int&b){a^=b^=a^=b;} 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(w,a[i/2+j+k]); 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 t[maxn]; void getinv(int*a,int*b,int n){ if(n==1){ b[0]=pow(a[0],mod-2); return; } int i; getinv(a,b,n>>1); pre(n<<1); memset(t,0,N<<2); memcpy(t,a,n<<2); ntt(t,1); ntt(b,1); for(i=0;i<N;i++)b[i]=mul(b[i],2-mul(b[i],t[i])); ntt(b,-1); for(i=n;i<N;i++)b[i]=0; } int a[maxn],b[maxn],c[maxn]; int main(){ int n,k,i,ans; scanf("%d",&n); for(k=1;k<=n;k<<=1); a[0]=1; for(i=1;i<=n;i++){ a[i]=mul(i,a[i-1]); b[i]=mul(i,a[i]); } pre(k<<1); ntt(a,1); for(i=0;i<N;i++)a[i]=mul(a[i],a[i]); ntt(a,-1); for(i=0;i<=n;i++)b[i]=de(a[i],b[i]); getinv(b,c,k); ans=0; for(i=0;i<=n;i++)ans=ad(ans,mul(a[i],c[n-i])); printf("%d",ad(ans,mod)); }
[Contest20180426]校门外的树的更多相关文章
- P1047 校门外的树
P1047 校门外的树 题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0 ...
- Vijos1448校门外的树 题解
Vijos1448校门外的树 题解 描述: 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现 ...
- OpenJudge计算概论-校门外的树
/*======================================================================== 校门外的树 总时间限制: 1000ms 内存限制: ...
- [swustoj 764] 校门外的树 Plus Plus
校门外的树 Plus Plus(0764) 问题描述 西南某科技大学的校门外长度为 L 的公路上有一排树,每两棵相邻的树之间的间隔都是 1 米.我们可以把马路看成一个数轴,马路的一端在数轴 1 的位置 ...
- 校门外的树 - Grids2808
校门外的树 问题描述: 某校大门外长度为 L 的马路上有一排树,每两棵相邻的树之间的间隔都是1 米.我们 可以把马路看成一个数轴,马路的一端在数轴0 的位置,另一端在L 的位置:数轴上的每 个整数点, ...
- 校门外的树 OpenJudge 1.6.06
06:校门外的树 总时间限制: 1000ms 内存限制: 65536kB 描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0 ...
- 【解题报告】VijosP1448校门外的树(困难版)
原题: 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的--如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:K=1,K=1,读入l.r ...
- Vijos P1103 校门外的树【线段树,模拟】
校门外的树 描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,……, ...
- Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】
校门外的树 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作: K=1,K= ...
随机推荐
- zigbee芯片 - JN5169
http://www.nxp.com/products/wireless-connectivity/2.4-ghz-wireless-solutions/support-resources-for-j ...
- VC++使用CImage在内存中Bmp转换Jpeg图片
之前写了一篇<VC++使用CImage在内存中Jpeg转换Bmp图片>,通过CImage实现了在内存中Jpeg转Bmp. 既然Jpeg能转Bmp,那CImage也支持Bmp转Jpeg,与上 ...
- php模式-数据映射模式
概念:简言之,数据映射模式就是将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作. 深入理解:数据映射,是在持久化数据存储层(一般是关系型数据库)和驻于内存的数据表现层之间进行双向数据 ...
- The 'brew link' step did not complete successfully
在mac 上更新node时遇到了一系列的问题: 卸载node重新安装之后提示: The 'brew link' step did not complete successfully 其实这里已经给出了 ...
- 快速排序和归并排序(C语言)
1.0快速排序算法 (1)分解 (2)递归求解 (3)合并 int partition(int a[],int p,int r) { int i=p,j=r+1; int x=a[p]; int te ...
- 【比赛】百度之星2017 初赛Round B
第一题 题意:给定n*m网络,定义两个棋子在同行同列则相互攻击,同时要求两个棋子的行和列不能一小一大,求满足条件的最大摆放的方案数. 题解:ans=C(max(n,m),min(n,m)),就是在ma ...
- 10款最新CSS3/jQuery菜单导航插件
这是我们在2014年收集的10款最新的CSS3 / jQuery菜单导航插件,不论从外观样式,还是功能扩展性,这些jQuery菜单一定可以满足大家的设计需求.这次我们收集的jQuery菜单,有水平 菜 ...
- LeetCode 10 Regular Expression Match
'.' Matches any single character.'*' Matches zero or more of the preceding element. The matching sho ...
- POJ2245 Lotto
Lotto Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6634 Accepted: 4201 Description ...
- solr requestHandler
使用哪一个handler: 1. 可以通过在url中追加有名字的handler(以 ' / ' 开头命名)的名称来指定使用哪一个handler. 如: <requestHandler name= ...