AGC 069
D. Tree and Intervals
感觉这个题可做啊,真该先开这个题的/fn
\(x_i\) 可以看作一端 \(\le i\),另一端 \(>i\) 的边数,进一步可以转化为:把 \(\le i\) 的点染成黑色,\(>i\) 的点染成白色,得到的总连通块数。
考虑判定怎样的“总连通块数”序列是可以被生成的。
一个个把点染黑,维护当前的黑色连通块数 / 总连通块数。
如果某一步总连通块数不变,那这步可以忽略。
如果某一步总连通块数增大,那黑色连通块数可能 \(+0\) 或 \(+1\)(如下图)。
如果某一步总连通块数减小,那黑色连通块数需要减小,有两种减小方式(如下图):
- 第一种方式:总连通块数 \(-cnt\),黑色连通块数 \(-cnt\)。
- 第二种方式:总连通块数 \(-(cnt+1)\),黑色连通块数 \(-cnt\),此时要保证有 \(\ge 2\) 个白色连通块(否则所有白色都消失了),或者这是最后一次操作。
最后操作完要保证黑色连通块数 \(\ge 1\)。
显然黑色连通块数越多越好,这样可以保证不被减到 \(\le 0\)。
我们可以贪心,维护当前能达到的最大黑色连通块数。由于第二种方式比第一种减少的更少,如果能用第二种方式就用第二种,否则用第一种。
设 \(f(i,j,s)\) 表示黑色连通块数为 \(j\),当前总连通块数为 \(s\) (这也确定了白色连通块的个数 \(=s-j\))的方案数,其中 \(j\) 这一维贪心计算。
枚举到下一个位置的连通块变化数,据此可以写出 \(O(n^4)\) 的转移:
int n;
modint f[505][505][505];
signed main()
{
n=read(),initmod();
For(i,2,n) f[1][1][i]=1;
For(i,1,n-1){
For(j,1,n) For(s,1,n) if(f[i][j][s].x) {
int wh=s-j;
For(k,1,n) if(s+k<=n) f[i+1][j+1][s+k]+=f[i][j][s];
f[i+1][j][s]+=f[i][j][s];
For(k,1,n) {
int jj=j-(k-1)-(wh<=1 && i<n-1);
if(jj>=1 && jj<=n && s-k>=1) f[i+1][jj][s-k]+=f[i][j][s];
}
}
}
modint res=0;
For(j,1,n)res+=f[n][j][1];
cout<<res.x;
return 0;
}
发现转移可以前缀和优化到 \(O(n^3)\),就做完了。submission
E. Pair of Sequences
列出答案的生成函数。
拆开分子与分母,两部分都是 q-binomial 的形式。
分子:
分母:
一边提取 \([y^i]\) 系数,一边提取 \([y^{S-i}]\) 系数。
由于 \(z^{\binom{i}{2}}\) 的存在,需要保证 \(\binom{i}{2}\le T\),\(i\) 只能枚举到 \(O(\sqrt T)\) 大小。
从小到大枚举 \(i\) 并暴力维护右边关于 \(z\) 的多项式即可,每次只需要做若干次形如 \(z^k-1\) 的乘/除。这部分复杂度 \(O(n\sqrt n)\)(设 \(n,m,S,T\) 同阶)。
当 \(i=0\) 时多项式为 \({S+m-1 \brack m-1}_z\),可以 \(O(n\log n)\) 算出(多项式 ln/exp)。