UOJ 633 「UR #21」你将如闪电般归来

k 减一。
Fkk+1 层树的 EGF。
立刻写出 Fk(x)=Fk1(x)(ex+ex2)=Fk1(x)coshx

初值 F0=x

这些东西让我联想起了自己对此类复杂的含微分方程的生成函数递推的失败尝试的回忆,让我有些退缩,但是这题真的是这样做(

设二元生成函数 F(x,t)=k0Fk(x)tk,类似地可以写出 xF=1+tFcoshx

容易解得 F(x)=etsinhxx0etsinhudu

考察其 [tk],有 Fk(x)=kj=0(sinhx)kj(kj)!x0(sinhu)jj!du

注意到积分 x0ejudu={ejx1j,j0x,j=0

这告诉我们 Fk 必然是 ecx,xecx线性组合。并且显然有 kck
通过一些没什么用的技巧可以获得 O(k2) 的解法,但数据范围显然提示我们洞察整式递推。

Fk(x)=Gk(sinhx),主要是为了简化积分形式,那么根据一开始的递推 Fk(x)=x0Gk1(sinhu)coshxdu=x0Gk1(sinhu)d(sinhu)(d(sinhu)du=coshu)=sinhx0Gk1(v)dvGk(x)=x0Gk1(v)dv

考察 F0(x)=x,那么 G0(x) 就应该等于反双曲函数 sinh1x。由于其 ODE 形式不够简洁,不是那么容易推导递推式,因此我们考虑从其导数 (sinh1x)=(1+x2)1/2 入手。
令其为 A(x),那么立刻知 A(x)(1+x2)=xA(x)nan=(1n)an2

B(x)=Gk(x),则 bn=ank1nk+1_A(x) 积分 k+1 次,代入递推式 (nk1)ank1=(2n+k)ank3(nk1)bnnk+1_=(2n+k)bn2(n2)k+1_n(n1)(nk1)bn=(nk1)(nk2)2bn2(nk1)[n(n1)bn+(nk2)2bn2]=0

接下来讨论一下,发现 n=k+1bn2=0,bn=1(k+1)!,则 n(n1)bn+(nk2)2bn2=[n=k+1](k1)!n(n1)bn+[(n2)(n1)+(12k)(n2)+k2]bn2=[n=k+1](k1)!k2x2B+(12k)x3B+x2(1+x2)B=xk+1(k1)!k2B+(12k)xB+(1+x2)B=xk1(k1)!

为了方便计算,我们作换元 x=lnx,那么需要提取的系数就变成了 xc,xclnx
X=x1/x2,令 P(x)=B(X),为了导出 P 的 ODE,我们事先作一些计算: P(x)=(1+x22)B(X)P(x)=(1+x22)2B(X)x3B(x)B(x)=(21+x2)P(x)B(x)=(21+x2)2P(x)+x3(21+x2)3P(x)

强行代入再经过一番化简后可得 k2(1+x2)P(x)+((1+2k)x+(12k)x3)P(x)+(x2+x4)P(x)=Xk1(k1)!(1+x2)

gn 为其 [xnlnx],可得 (n+k)2gn+(nk2)2gn2=0

fn 为其 [xn],可得 (n+k)2fn+(nk2)2fn2+2(n+k)gn+2(nk2)gn2=[xn]Xk1(k1)!(1+x2)

考虑边界值,复习一下前面解出的微分方程可知 fk=12kkj=1(1)j(kj)!j!jgk=12kk!

如此从大至小递推即可。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <cstdio>
#include <cstring>
using namespace std;
const int K = 1e7 + 2;
const int mod = 998244353;
const int inv2 = 499122177;
inline int fpow(int a,int b)
{
int ret = 1;
for(;b;b >>= 1)
(b & 1) && (ret = (long long)ret * a % mod),a = (long long)a * a % mod;
return ret;
}
int k;
long long n;
int fac[K + 5],ifac[K + 5],inv[K + 5];
int vis[K + 5],cnt,prime[K + 5],pw[K + 5];
int f[K + 5],g[K + 5],ans;
int main()
{
scanf("%d%lld",&k,&n),--k;
fac[0] = 1;
for(register int i = 1;i <= k;++i)
fac[i] = (long long)fac[i - 1] * i % mod;
ifac[k] = fpow(fac[k],mod - 2);
for(register int i = k;i;--i)
ifac[i - 1] = (long long)ifac[i] * i % mod;
for(register int i = 1;i <= k;++i)
inv[i] = (long long)ifac[i] * fac[i - 1] % mod;
pw[0] = n == 1 ? 1 : 0,pw[1] = 1;
for(register int i = 2;i <= k;++i)
{
if(!vis[i])
pw[prime[++cnt] = i] = fpow(i,(n - 1) % (mod - 1));
for(register int j = 1;j <= cnt && i * prime[j] <= k;++j)
{
vis[i * prime[j]] = 1,pw[i * prime[j]] = (long long)pw[i] * pw[prime[j]] % mod;
if(!(i % prime[j]))
break;
}
}
n %= mod;
f[k] = (long long)ifac[k] * fpow(2,mod - 1 - k) % mod;
for(register int i = k - 2;i >= 0;i -= 2)
f[i] = f[i + 2] * (mod - (long long)(i + 2 + k) * (i + 2 + k) % mod) % mod * inv[k - i] % mod * inv[k - i] % mod;
for(register int i = k;i > 0;i -= 2)
ans = (ans + (long long)f[i] * pw[i] % mod * n) % mod;
ans = (ans + (long long)f[0] * pw[0] % mod * n % mod * inv2) % mod;
int t = fpow(2,mod - k);
for(register int i = 0;2 * i <= k - 1;++i)
g[k - 1 - 2 * i] = (long long)(i & 1 ? mod - t : t) * ifac[i] % mod * ifac[k - 1 - i] % mod;
for(register int i = k + 1;i >= 2;i -= 2)
g[i] = (g[i] + g[i - 2]) % mod;
for(register int i = 2;i <= k + 2;++i)
g[i] = (g[i] + (long long)(mod - f[i - 2]) * (mod + 2 * (i - k - 2)) + (long long)(mod - f[i]) * (2 * (i + k))) % mod;
f[k] = 0;
for(register int i = 1;i <= k;++i)
f[k] = (f[k] + (long long)(i & 1 ? mod - inv[i] : inv[i]) * ifac[i] % mod * ifac[k - i]) % mod;
f[k] = (long long)f[k] * fpow(2,mod - 1 - k) % mod;
for(register int i = k - 1;i >= 0;--i)
f[i] = (f[i + 2] * (mod - (long long)(i + 2 + k) * (i + 2 + k) % mod) + g[i + 2]) % mod * inv[k - i] % mod * inv[k - i] % mod;
for(register int i = 1;i <= k;++i)
ans = (ans + (long long)f[i] * pw[i] % mod * i) % mod;
ans = 2 * ans % mod;
printf("%d\n",ans);
}

Related Issues not found

Please contact @Alpha1022 to initialize the comment