Public NOIP Round #1 Div.1
Problem C. 波特分组
记 \(S=\sum k_i\)。
\(O(n\sqrt{S}+S)\) Solution
将硬币正面记为 \(1\),反面记为 \(0\)。
首先概率转计数:求有多少个 01 序列,能够使得这 \(k\) 个波特分到一个组里。
为了方便,我们可以钦定这些波特都要分到 A 组中,最终答案再乘以 \(2\)。
我们设最后一个被分到 A 组中的波特为 \(pa\),最后一个被分到 B 组中的波特为 \(pb\)。设 \(p=\min(pa,pb)\),那么 \(p\) 之后的位置,无论是 \(0\) 还是 \(1\),都会被分到另一个组里面。
那么我们对 \(p\) 进行分类讨论:
-
\(p=pa\),\([p+1,n]\) 中的波特都会被分到 B 组。显然需要满足 \(p\geq b_k\)。
进一步分类:
- \(p=b_k\)。由于 \(k\) 个指定的波特必须分到 A 组,那么还需要将剩下的 \(n-k\) 个 \(1\) 填入 \(b_k-k\) 个位置里面。方案数为 \(\binom{b_k-k}{n-k}\times 2^{2n-p}\)。
- \(p>b_k\)。\(p\) 这个位置必须填 \(1\),那么还要将剩下的 \(n-k-1\) 个 \(1\) 填入 \(p-k-1\) 个位置里面。方案数为 \(\binom{p-k-1}{n-k-1}\times 2^{2n-p}\)。
-
\(p=pb\),\([p+1,n]\) 中的波特都会被分到 A 组。需要满足 \(p\ne b_i\)。
我们可以增加两个点 \(b_0=0,b_{k+1}=2n\)。
如果一个 \(p\) 满足 \(b_i<p<b_{i+1}\),那么要将剩下的 \(n-1\) 个 \(0\) 填入 \(p-i-1\) 个位置里面,方案数为 \(\binom{p-i-1}{n-1}\times 2^{2n-p}\)。
注意 \(p\ne 2n\),因为 \(\min(pa,pb)\) 一定小于 \(2n\)。
对于情况 2,我们可以将式子化为 \(\binom{p-i-1}{n-1}\times 2^{2n-(p-i)}\times 2^{-i}\),处理出 \(\binom{x-i}{n-1}\times 2^{2n-x}\) 的前缀和即可。
对于情况 1,不同的 \(k\) 不会超过 \(O(\sqrt{S})\) 量级,所以我们对每个 \(k\) 分别处理前缀和即可。
int n,Q;const ll mod=998244353,inv2=(mod+1)>>1;inline ll Mod(ll x){return (x>=mod)?(x-mod):(x);}inline void Add(ll &x,ll y){x=Mod(x+y);}ll fac[N],caf[N],pw[N],wp[N];ll QuickPow(ll x,ll y){ll res=1;while(y){if(y&1) res=res*x%mod;x=x*x%mod; y>>=1;}return res;
}void Init(){fac[0]=caf[0]=1;for(int i=1;i<=(n<<1);i++) fac[i]=fac[i-1]*i%mod;caf[n<<1]=QuickPow(fac[n<<1],mod-2);for(int i=(n<<1)-1;i;i--) caf[i]=caf[i+1]*(i+1)%mod;pw[0]=wp[0]=1;for(int i=1;i<=(n<<1);i++) pw[i]=Mod(pw[i-1]<<1),wp[i]=wp[i-1]*inv2%mod;
}inline ll C(int x,int y){if(x<0||y<0||x<y) return 0;return fac[x]*caf[y]%mod*caf[x-y]%mod;
}namespace Subtask1{int k[N],c[N],m;vector<int> q[N];ll f[850][N],g[N];void Solve(){Init();for(int i=1;i<=Q;i++){read(k[i]); c[i]=k[i];q[i].push_back(0);for(int j=1;j<=k[i];j++){int x; read(x);q[i].push_back(x);}q[i].push_back(n<<1);}sort(c+1,c+Q+1);m=unique(c+1,c+Q+1)-c-1;for(int i=1;i<=m;i++){for(int j=n;j<(n<<1);j++)f[i][j]=Mod(f[i][j-1]+C(j-c[i]-1,n-c[i]-1)*pw[2*n-j]%mod);}for(int i=n;i<(n<<1);i++)g[i]=Mod(g[i-1]+C(i-1,n-1)*pw[2*n-i]%mod);for(int i=1;i<=Q;i++){int tk=lower_bound(c+1,c+m+1,k[i])-c;ll ans=0;for(int j=0;j<(signed)q[i].size()-1;j++){if(q[i][j]==2*n) continue;int L=q[i][j]+1-j,R=q[i][j+1]-1-j;ll res=Mod(g[R]-g[L-1]+mod)*wp[j]%mod;Add(ans,res);}if(q[i][k[i]]!=n*2){Add(ans,C(q[i][k[i]]-k[i],n-k[i])*pw[2*n-q[i][k[i]]]%mod);Add(ans,Mod(f[tk][(n<<1)-1]-f[tk][q[i][k[i]]]+mod));}ans=Mod(ans<<1)*QuickPow(pw[n<<1],mod-2)%mod;printf("%lld\n",ans);}}
}signed main(){read(n),read(Q); Init();Subtask1::Solve();return 0;
}