【UOJ #424. 【集訓隊作業2018】count】【笛卡爾樹+容斥原理】

題意

fA(l,r)f_A(l,r)表示序列AA中,A[l..r]A[l..r]中最大值的位置。若存在若干個最大值,則取最靠前的那一個。定義兩個序列A,BA,B同構,當且僅當兩個序列長度相等,且對於任意lrl\le r都有fA(l,r)=fB(l,r)f_A(l,r)=f_B(l,r)。問有多少個長度爲nn且不同構的序列,其中的元素爲11mm中的整數,且每個整數在其中至少出現一次。
n,m105n,m\le 10^5

分析

有一種挺妙的生成函數做法,可以看這篇博客

若我們對序列建笛卡爾樹,容易發現兩個序列同構,當且僅當它們的笛卡爾樹形狀相同。並且不同構的序列,和最長左鏈(某個節點到根的路徑中,作爲左兒子的次數+1)不超過mm的笛卡爾樹是一一對應的。問題轉化成求nn個節點且最長左鏈不超過mm的笛卡爾樹數量。

通過多叉樹轉二叉樹的方法(二叉樹的左兒子代表該節點在多叉樹上最左邊的兒子,右兒子代表該節點在多叉樹上右邊第一個兄弟),將nn個節點的二叉樹與n+1n+1個節點(要補一個根)的多叉樹一一對應,且二叉樹的最長左鏈不超過mm,當且僅當其對應的多叉樹的深度不超過mm(根節點深度爲00)。問題轉化爲求n+1n+1個節點深度不超過mm的多叉樹數量。

n+1n+1個節點多叉樹的入棧出棧序看成括號序,就是形如(X)(X),其中XX是由nn對括號組成的合法括號序。將左括號看成+1+1,右括號看成1-1,該多叉樹深度不超過mm當且僅當括號徐的每個前綴均不超過mm。問題轉化爲求nn對括號組成且前綴不超過mm的合法括號序數量。

用類似證明卡特蘭數的思想,將其放到二維平面上,變爲求從(0,0)(0,0)走到(2n,0)(2n,0),每次橫座標+1+1,縱座標+1+11-1,且不經過y=m+1y=m+1y=1y=-1的路徑數量。這個可以用容斥來算。具體來說,設其先經過若干次y=m+1y=m+1,再經過若干次y=1y=-1,再經過若干次y=m+1y=m+1,如此類推。則把起點沿y=m+1y=m+1對稱,再沿y=1y=-1對稱,再沿y=m+1y=m+1對稱,如此類推。再計算最終得到的起點到(2n,0)(2n,0)的路徑數量,就是對應的方案數。容斥係數爲(1)(-1)^{交錯次數}

時間複雜度O(n)O(n)

代碼

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 200005;
const int MOD = 998244353;

int n, m, jc[N], ny[N];

int C(int n, int m)
{
	return (LL)jc[n] * ny[m] % MOD * ny[n - m] % MOD;
}

int main()
{
	scanf("%d%d", &n, &m);
	if (n < m) {puts("0"); return 0;}
	m++;
	jc[0] = jc[1] = ny[0] = ny[1] = 1;
	for (int i = 2; i <= n * 2; i++) jc[i] = (LL)jc[i - 1] * i % MOD, ny[i] = (LL)(MOD - MOD / i) * ny[MOD % i] % MOD;
	for (int i = 2; i <= n * 2; i++) ny[i] = (LL)ny[i - 1] * ny[i] % MOD;
	int ans = C(n * 2, n);
	for (int i = 0, x = 0; ; i++)
	{
		if (i & 1) x = -2 - x;
		else x = m * 2 - x;
		if (abs(x) > n * 2) break;
		if (i & 1) (ans += C(n * 2, (n * 2 - x) / 2)) %= MOD;
		else (ans += MOD - C(n * 2, (n * 2 - x) / 2)) %= MOD;
	}
	for (int i = 0, x = 0; ; i++)
	{
		if (i & 1) x = m * 2 - x;
		else x = -2 - x;
		if (abs(x) > n * 2) break;
		if (i & 1) (ans += C(n * 2, (n * 2 - x) / 2)) %= MOD;
		else (ans += MOD - C(n * 2, (n * 2 - x) / 2)) %= MOD;
	}
	printf("%d\n", ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章