专栏文章

题解:P13909 「TFXOI Round 3」就此别过

P13909题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mio21vx2
此快照首次捕获于
2025/12/02 12:05
3 个月前
此快照最后确认于
2025/12/02 12:05
3 个月前
查看原文
看不懂官方题解。
显然二项式反演,定义 gig_i 表示恰 ii 个断点的方案数,fif_i 为选定 ii 个断点,剩余任意的方案数,有:
gi=j(1)ij(n1jn1i)fjg_i=\sum_j (-1)^{i-j}{n-1-j\choose n-1-i}f_j
枚举多余断点,直接容斥易得,这一步可以卷积优化,比较平凡不再赘述。
考虑如何得到 ff,注意到每一段若长度确定,要么上升要么下降,再枚举不同段的大小关系即可完全确定序列,但是对于长度为 11 的段会多算一遍,因为上升和下降没有区别。不妨要求 11 的段上升,对限制容斥可得:
fi=j(1)j(i+1j)(nj1ij)(i+1)!2i+1jf_i=\sum_j (-1)^j{i+1\choose j}{n-j-1\choose i-j}(i+1)!2^{i+1-j}
这里要特判 nn 个长度为 11 的段的情况。注意到这也可以拆为一次卷积,时间复杂度 O(nlogn)O(n\log n),共两次卷积。
CPP
inline void solve(){
	cin>>n;
	for(int i=1;i<=n;i++) bas[i]=reduce(bas[i-1]<<1);
	for(int i=0;i<n;i++) a[i]=(i&1?Mod-ifac[i]:ifac[i])*fac[n-1-i]%Mod;
	for(int i=0;i<n;i++) b[i]=ifac[i+1]*ifac[i]%Mod*bas[i+1]%Mod;
	NTT::polymul(n-1,a,b,f);
	for(int i=0;i<n;i++) f[i]=f[i]*fac[i+1]%Mod*ifac[n-i-1]%Mod*fac[i+1]%Mod;
	f[n-1]=(f[n-1]+(n&1?Mod-1:1)*fac[n])%Mod;
	for(int i=0;i<n;i++) f[i]=(i&1?Mod-f[i]:f[i])*fac[n-1-i]%Mod;
	for(int i=0;i<n;i++) a[i]=ifac[i];
	NTT::polymul(n-1,f,a,g);
	for(int i=0;i<n;i++) cout<<(i&1?Mod-g[i]:g[i])*ifac[n-1-i]%Mod<<'\n';
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...