一排格子,每個格子黑白顏色\(c_i\)。一開始從某個位置\(s\)開始,\(s\)上放顏色\(c_i\)的棋子。每次選擇一個和有棋子格子相鄰的空格子\(x\),放顏色為\(c_x\)的棋子,並找到離\(x\)最近的顏色同為\(c_x\)棋子\(y\),將\(x,y\)之間的棋子都反色。如果找不到就算了。
(其實就是黑白棋)
兩人博弈,先手最大化黑子個數。
對於所有的\(s\),分別求:對所有的染色方案\(\{c_i\}\)求最終黑子個數的和(期望)。
\(n\le 2*10^5\)
發現了性質之后它似乎就變成一道簡單題了……
雖然我是打表發現的。
可以發現無論怎樣操作,中間的連通塊不可能出現黑白黑的情況。可以歸納。
根據以上結論,進一步發現,如果兩端同色,最終所有棋子一定同色;如果兩端異色,先手希望盡量往黑色那邊走,后手希望盡量往白色那邊走,誰先走到,中間一大塊(即:除去兩端的同色段)就是誰的。
根據這個性質計算即可。
有個比較陽間的算法:首先算兩端同色。對於兩端異色,設左端連續段為\([1,L]\),右端連續段為\([R,n]\),當\(s-L\neq R-s\)時,一種狀態和它完全取反的狀態的答案是互補的。所以只需要特別計算\(s-L=R-s\)的情況多加一次即可。
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
#define N 200005
#define ll long long
#define mo 998244353
ll qpow(ll x,ll y=mo-2){
ll r=1;
for (;y;y>>=1,x=x*x%mo)
if (y&1)
r=r*x%mo;
return r;
}
int n;
ll pw2[N*2],f[N];
ll ans[N];
void calc(int n){
pw2[0]=1;
for (int i=1;i<=n*2;++i)
pw2[i]=pw2[i-1]*2%mo;
ll sum=0;
(sum+=pw2[n-2]*n)%=mo;
(sum+=pw2[n-2]*n)%=mo;
for (int i=1;i<=n;++i)
ans[i]=sum;
// for (int i=1;i<=n;++i)
// for (int L=1;L<=n;++L){
// int R=i*2-L;
// if (R>=L+3 && R<=n)
// (ans[i]+=(R-L-1)*pw2[R-L-3])%=mo;
// }
// for (int i=1;i<=n;++i)
// for (int t=2;t<=i-max(2*i-n,1);++t)
// (ans[i]+=(2*t-1)*pw2[2*t-3])%=mo;
for (int i=2;i<=n;++i)
f[i]=(f[i-1]+(2*i-1)*pw2[2*i-3])%mo;
for (int i=3;i<=n-2;++i){
// assert(i-max(2*i-n,1)>=0);
(ans[i]+=f[i-max(2*i-n,1)]-f[2-1]+mo)%=mo;
}
ll inv=qpow(pw2[n]);
for (int i=1;i<=n;++i)
ans[i]=ans[i]*inv%mo;
}
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
scanf("%d",&n);
if (n==1){
printf("%d\n",qpow(2));
return 0;
}
calc(n);
for (int i=1;i<=n;++i)
printf("%lld\n",ans[i]);
return 0;
}