题解 大天桥

传送门

因为太困了赛时并没有认真做这个题

  • 有些多项式真的是可以手动求逆的
  • 关于 \(x\) 的非整数次多项式(主要指 \(F(x)=\sqrt{a+bx}\)\(a, b\) 为常数)一类的东西可以牛顿二项式定理展开
  • 可以使用分子/分母有理化让未知数在分式上来回挪

发现是要计算有多少种染色方案能建立天桥
把天桥看成有色括号序列,那么可以枚举最后一个括号所在的括号大小
\(f_i\) 为有 \(i\) 对括号时的答案,\(g_i\) 为有 \(i\) 对括号且有一种颜色不能选时的方案数
那么

\[f_i=k\sum\limits_{j=0}^{i-1}g_jf_{i-j-1} \]

\[g_i=(k-1)\sum\limits_{j=0}^{i-1}g_jg_{i-j-1} \]

这样就可以分治 NTT 了

然后考虑怎么优化:
需要 \(O(n)\),那么可能需要手动多项式求逆
尝试求出 \(G(x)=\sum g_ix^i\) 的封闭形式
发现

\[\begin{aligned} G(x)&=1+(k-1)\sum\limits_{i=1}\sum\limits_{j=0}^{i-1}g_jg_{i-j-1}\\ &=1+(k-1)x\sum\limits_{i=0}\sum\limits_{j=0}g_ig_j\\ &=1+(k-1)xG^2(x) \end{aligned}\]

于是

\[x(k-1)G^2(x)-G(x)+1=0 \]

扔进求根公式里,得

\[G(x)=\frac{1\pm\sqrt{1-4x(k-1)}}{2x(k-1)} \]

只有一个根是合法的,是哪一个呢?
发现现在我们知道 \([x^0]G(x)=0\),那么尝试代入验证一下
但是直接代入会让分母为 0,需要先利用 \((a+b)(a-b)=a^2-b^2\) 分母有理化
可以得到

\[G(x)=\frac{2}{1\pm\sqrt{1-4x(k-1)}} \]

因为

\[\lim\limits_{x\to 0}\frac{2}{1+\sqrt{1-4x(k-1)}}=\frac{2}{1+\sqrt{1}}=1=[x^0]G(x) \]

所以可以舍去另一个不合法的根
得到

\[G(x)=\frac{2}{1-\sqrt{1-4x(k-1)}} \]

同理得

\[F(x)=\frac{1}{1-kxG(x)} \]

这个根号带着十分麻烦而且也不太能拆,所以可以设一个 \(u=\sqrt{1-4x(k-1)}\)
此时将 \(G\) 代入 \(F\)

\[F(x)=\frac{2k-2}{ku+k-2} \]

然而这个东西仍然不能 \(O(n)\)
要想 \(O(n)\),就要把多项式求逆去掉
将分母有理化得

\[F(x)=\frac{ku-k+2}{2(1-k^2x)} \]

\(H=\frac{ku-k+2}{2}\),那么 \((1-k^2x)F=H\)
发现这样的话 \(f_i=h_i+k^2f_i-1\),就可以线性求出了
那么现在要线性求出 \(H\)
与 Catalan 数类似的,使用牛顿二项式定理拆式子

\[\begin{aligned} u&=\sqrt{1-4x(k-1)}\\ &=(1-4x(k-1))^{\frac{1}{2}}\\ &=\sum\limits_{i=0}\binom{\frac{1}{2}}{i}(-4x(k-1))^i\\ &=1+\sum\limits_{i=0}\frac{(\frac{1}{2})^{\underline{i}}}{i!}(-4x(k-1))^i\\ \end{aligned}\]

然后求这个 \(\dfrac{(\frac{1}{2})^{\underline{i}}}{i!}\)

\[\frac{(\frac{1}{2})^{\underline{i}}}{i!}=(-1)^{i-1}\frac{1}{2^i}\frac{(2i-3)!!}{i!} \]

拆一下双阶乘

\[(2i-3)!!=\frac{(2i-2)!}{(2i-2)(2i-4)\cdots 2}=\frac{(2i-2)!}{2^{i-1}(i-1)!} \]

再大力回代得到

\[u=1-\sum\limits_{i\geqslant 1}\frac{2(2i-2)!(k-1)^i}{(i-1)!i!} \]

再代入 \(H\) 得到

\[H=1-\sum\limits_{i\geqslant 1}\frac{(2i-2)!k(k-1)^i}{(i-1)!i!} \]

于是可以 \(O(n)\) 求出答案

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 10000010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline ll read() {
	ll ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;
ll k, mod;

namespace force{
	ll f[N], g[N];
	void solve() {
		f[0]=g[0]=1;
		for (int i=1; i<=n; ++i) {
			for (int j=0; j<i; ++j) {
				f[i]=(f[i]+g[j]*f[i-j-1])%mod;
				g[i]=(g[i]+g[j]*g[i-j-1])%mod;
			}
			f[i]=f[i]*k%mod;
			g[i]=g[i]*(k-1)%mod;
		}
		printf("%lld\n", (f[n]%mod+mod)%mod);
	}
}

namespace task1{
	ll fac[N], inv[N], inv2[N], f[N], h[N];
	void solve() {
		fac[0]=fac[1]=1; inv[0]=inv[1]=1; inv2[0]=inv2[1]=1; h[0]=f[0]=1;
		for (int i=2; i<=2*n; ++i) fac[i]=fac[i-1]*i%mod;
		for (int i=2; i<=2*n; ++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
		for (int i=2; i<=2*n; ++i) inv2[i]=inv2[i-1]*inv[i]%mod;
		ll tem=k;
		for (int i=1; i<=n; ++i) {
			tem=tem*(k-1)%mod;
			h[i]=-fac[2*i-2]*inv2[i]%mod*inv2[i-1]%mod*tem%mod;
		}
		for (int i=1; i<=n; ++i) f[i]=(h[i]+k*k%mod*f[i-1])%mod;
		printf("%lld\n", (f[n]%mod+mod)%mod);
	}
}

signed main()
{
	freopen("flyover.in", "r", stdin);
	freopen("flyover.out", "w", stdout);

	n=read()>>1; k=read(); mod=read(); k%=mod;
	// force::solve();
	task1::solve();

	return 0;
}
posted @ 2022-05-14 20:02  Administrator-09  阅读(2)  评论(0编辑  收藏  举报