CF1930E 题解
sunkuangzheng · · 题解
给你
n,k ,有一个长度为n 的数组a ,初始时a_i=i 。一次操作可以选择一个长度为2k+1 的子序列,删除前后k 个元素,留下中间的一个。对于k \in [1,\lfloor \dfrac{n-1}{2} \rfloor] ,求出如果进行任意次操作,能得到多少不同的数组,模998244353 。
容易发现
考虑对于固定的
寻找充要条件。从
当
- 必要性。
删除一些
1 不会增加0 的数量,也不会增加0 两边1 的数量。故如果初始不存在p 操作至x=2k 时一定也不会存在p ,不合法。
- 充分性。
我们找到
p 的位置。如果某一侧有\ge 3k 个1 ,显然我们可以从一边删除2k 个。这样两边都会剩下[k,3k) 个1 。因为两边1 数量的总和是2k 的倍数,所以一定存在一种方案把两边都删到恰好k 个1 ,再进行一次操作即可。
这个条件不好直接计数,考虑用总数
总时间复杂度
/**
* author: sunkuangzheng
* created: 15.02.2024 22:43:43
**/
#include<bits/stdc++.h>
#ifdef DEBUG_LOCAL
#include <mydebug/debug.h>
#endif
using ll = long long;
const int N = 2e6+5,mod = 998244353;
using namespace std;
int T,n,f[N],g[N];
int qp(int a,int b){
int r = 1;
for(;b;b >>= 1,a = 1ll * a * a % mod) if(b & 1) r = 1ll * r * a % mod;
return r;
}void los(){
auto C = [&](int n,int m){
return (n < 0 || m < 0 || n < m ? 0 : 1ll * f[n] * g[m] % mod * g[n - m] % mod);
};
cin >> n;
for(int i = 1;i <= (n - 1) / 2;i ++){
int ans = 0;
for(int j = i * 2;j <= n;j += i * 2)
ans = ((ans + C(n,j)) % mod - C(2 * i + n - j - 1,2 * i - 1) + mod) % mod;
cout << ans + 1 << " ";
}cout << "\n";
}int main(){
f[0] = g[0] = 1,n = 1e6;
for(int i = 1;i <= n;i ++) f[i] = 1ll * f[i - 1] * i % mod;
g[n] = qp(f[n],mod - 2);
for(int i = n - 1;i >= 1;i --) g[i] = 1ll * g[i + 1] * (i + 1) % mod;
ios::sync_with_stdio(0),cin.tie(0);
for(cin >> T;T --;) los();
}