DTOJ 4109: 结绳(knot)

时间限制: 2 Sec 内存限制: 512 MB
提交: 26 解决: 10
[提交][状态][博客][加入收藏]
题目描述
【题目背景】

聚拢,成形,捻转,回绕,时而返回,暂歇,再联结。这就是组纽。这就是时间。

【题目描述】

小H陷入了无尽的迷茫之中。一个谜题出现在小H前面。

这是一个带有n种绳结的谜题,每种绳结有si个,每个绳结有独立的标号。

小H终于发现了解开这个谜题的方法。对于每一个绳结,如果有另一个不同种类的绳结与它配对,那么这个两个绳结就会解开。如果解开了所有的绳结,那么这个谜题也就解开了。

现在小H又想知道解开谜题的方案数了。而你只需要回答方案数对998244353取模后的结果就可以了。

输入
第一行,一个整数n,表示有n种绳结。

第二行,n个整数,第i个整数si表示第i种绳结有si个。

输出
仅一行,输出一个整数,代表方案数对998244353取模后的结果。

样例输入
2
2 2
样例输出
2
提示
见选手目录下knot/knot1.in和knot/knot1.ans

【样例输入输出1解释】

我们用A1,A2,B1,B2表示四个绳结。

那么合法方案为A1-B1,A2-B2和A1-B2,A2-B1。

【样例输入输出2】

见选手目录下knot/knot2.in和knot/knot2.ans

【数据范围和约定】

对于全部的数据,1≤n≤1e5,1≤si≤1e5。令S=∑si,S<=2e5。

题解:
要求的是符合条件的方案数,但“每个绳结都与不同种类匹配”这个条件不好限制,故考虑容斥,即问题转化为求至少i对配错,其他对无限制的方案数。
所以要求的就是:1.将i*2个无限制配为i对的方案数;2.i对配错的方案数。
1.组合数显然,或用DP也可,记为g。
2.这i对是由n种中每种选出若干对,显然是一个背包模型。考虑记f[i][j]为前i种选出j对配错的方案数,转移:f[i][j]=sigma(k=0~min(j,a[i]/2)){f[i-1][j-k]C(a[i],k2)g[k]}。
然而这时O(n
S)的,考虑f的状态书是无法优化的,只能优化转移过程。
观察转移方程,发现这是一个卷积,然而若每次转移都NTT一次,由于j的范围是累加的,故无法优化。
所以一定不能让i-1转移到i,而是要使转移的次数优化到log,因为每次转移都要O(SlogS)。
所以考虑分治(其实也是DP优化的常用方法),i不能再表示前i个,而是替换为l,r表示区间l~r内选j对,分治左右区间,那么合并显然是卷积的形式,故每次合并跑一边NTT即可,效率O(nlognlogS)。
后来才发现原来这东西叫分治FFT

WA警示:
1.reverse数组要在分治后写,以防分治下去的影响;
2.NTT的预处理要在合并前写,项数要计算得刚好,因为每层都是倍增的;
3.r[i]=(r[i>>1]>>1)|((i&1)<<(x-1)),i&1脑残写成r[i]&1.
TLE警示:
函数内开大小为N的数组是可以的,因为只有log层,但不能写t[N]={0},会TLE(以前一直天真地以为这是O(1)的,然而并没有这么便宜的清零操作)。

你可能感兴趣的:(#,分治,#,DP计数,#,多项式/生成函数)