[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= ...
随机推荐
- 分享一些JavaScript简易小技巧
特性检测而非浏览器检测 因为某某特性某浏览器不支持,我们经常的做法是在代码中直接先做浏览器判断如: 1 if(Broswer.isFirfox){ 2 //do something 3 } 其 ...
- <video>标签的特性
以前的网页视频 过去还没有HTML5的时候,我们处理网页视频的时候,都是通过Flash插件来实现的,然而,并非所有浏览器都有同样的插件. 现在有了HTML5带来的video元素,开发者能够很方便地将视 ...
- tomcat内存配置及配置参数详解
1.jvm内存管理机制: 1)堆(Heap)和非堆(Non-heap)内存 按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟 ...
- fscanf函数的应用
转摘自:http://blog.csdn.net/mxgsgtc/article/details/13005675 以前老是被从文本里读取文件,然后逐个的进行字符解析,感觉非常的慢,自从知道了fsca ...
- node搭建文件服务器
python可以在目录下python -m http.server 8080来启动一个静态文件服务器,使用node实现一个 运行node fileServer.js D:\lanFeature 即可将 ...
- iOS12、iOS11、iOS10、iOS9常见适配
作者:花丶满楼 链接:https://juejin.im/post/5c49a7d0518825254e4d46fc 一.iOS12(Xcode10) 1.1.升级Xcode10后项目报错 不允许多个 ...
- org.apache.http.conn.HttpHostConnectException: Connection to xxx refused.
if you are using emulator to run your app for local server. mention the local ip as 10.0.2.2 and hav ...
- Codeforces Round #300 解题报告
呜呜周日的时候手感一直很好 代码一般都是一遍过编译一遍过样例 做CF的时候前三题也都是一遍过Pretest没想着去检查... 期间姐姐提醒说有Announcement也自信不去看 呜呜然后就FST了 ...
- POJ1220(大数进制转换)
NUMBER BASE CONVERSION Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 4652 Accepted: ...
- 【uva11421】玩纸牌
数学期望. #include<bits/stdc++.h> ; using namespace std; double d[N][N],p; int main(){ ;double p;s ...