noip 模拟 28 客星璀璨之夜
虽然不清楚是不是那两人的力量
在那个风暴肆虐的夜晚,的确有一瞬
真的在那一瞬间,在云破天开的时候
透过空隙中看到的璀璨星空,不知为何倒映眼中不能忘怀 ” ——《奇迹召唤星辰》
时空轮回,我们回到xm的仲夏夜,在行星运动之前,我们掌握了他们的运动规律。
在一个行星湮灭之后,恰好构成了上个行星湮灭时的序列状态...
令 \(dp[i][j]\) 为第 \(i\) 层(即有\(i\)个反物质行星)时经过编号为 \(j\) 的边的概率。
转移时枚举反物质行星,将其湮灭,此时的新状态即为上一层的答案,对应更新即可。
for(re int i=2;i<=n;i++) {
for(re int j=1,tot;j<=i;j++) {
// 「 左移 」
(p[i][j*2-1]+=inv[i*2])%=mol;
tot=0;
for(re int k=1;k<=i*2;k++) {
if(k<=j*2-2||k>=j*2+1) tot++;
(p[i][k]+=p[i-1][tot]*inv[i*2]%mol)%=mol;
}
// 「 右移 」
(p[i][j*2]+=inv[i*2])%=mol;
tot=0;
for(re int k=1;k<=i*2;k++) {
if(k<=j*2-1||k>=j*2+2) tot++;
(p[i][k]+=p[i-1][tot]*inv[i*2]%mol)%=mol;
}
}
}
我们发现对于一层编号的边(设编号为\(k\))
\(dp[i][k]=dp[i-1][k-2]*(k-2)+dp[i-1][k-1]+dp[i-1][k]*(2*i-k)\);
手膜真累,忘打表了,这样我们就省下了一层循环。
for(re int i=2;i<=n;i++) {
(p[i][1]+=inv[i*2])%=mol;
(p[i][1]+=p[i-1][1]*(2*i-1)%mol*inv[2*i]%mol)%=mol;
for(re int k=2;k<=i*2;k++) {
(p[i][k]+=p[i-1][k-2]*(k-1)%mol*inv[i*2]%mol)%=mol;
(p[i][k]+=p[i-1][k-1]*inv[i*2]%mol)%=mol;
(p[i][k]+=p[i-1][k]*(2*i-k)%mol*inv[i*2]%mol)%=mol;
(p[i][k]+=inv[i*2])%=mol;
}
}