[CF1188E] Problem from Red Panda 题解
[CF1188E] Problem from Red Panda 题解
考虑每个位置的操作次数
考虑原序列和操作序列的关系,断言:操作序列(假设后)和原序列一一对应。
证明:
形式化地说,假设有操作序列,最后得到的气球序列为 ,欲证 。 充分性是显然的,论证必要性:考察气球序列中的位置
,有 ,有 ,因为 ,所以 ,证毕。
得到这个之后,我们只需要计数操作序列即可,并且不用管算重的问题。
发现操作总数
考虑操作序列合法的充要条件,首先显然有
证明:
必要性显然。关于充分性,考虑构造一组合法操作序列,不难发现,随着
的增大, 一定单调不降,对于一个时刻,一定有一部分操作是必须要放到一些位置上,为了满足下界的需求,剩余有一些操作是可以随便放的,所以每次 的增加时,把本来可以随便放的操作放到增加的 的位置即可,因为有 ,所以总是能够满足 的需求。
根据不等式
剩下的部分是一些简单的组合计数,需要满足:前
容斥后
这里的答案就等于:
需要注意的是,如果一个时刻
代码实现
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
//#define int long long
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 2e6 + 10, mod = 998244353;
int k, a[N], fac[N], ifac[N], cnt[N], m;
int qmi(int a, int b) {
int res = 1;
while(b) {
if(b & 1) res = 1ll * res * a % mod;
a = 1ll * a * a % mod, b >>= 1;
}
return res;
}
int C(int n, int m) {
if(n < m) return 0;
return 1ll * fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> k;
for(int i = 1; i <= k; i ++) cin >> a[i], m = max(m, a[i]);
fac[0] = ifac[0] = 1;
for(int i = 1; i < N; i ++) fac[i] = 1ll * fac[i - 1] * i % mod;
ifac[N - 1] = qmi(fac[N - 1], mod - 2);
for(int i = N - 2; i; i --) ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
int r = 0, w = 0;
long long ans = 0;
sort(a + 1, a + k + 1);
for(int s = 0, j = 1; s <= m; s ++) {
while(j <= k && a[j] < s) cnt[a[j] % k] ++, j ++;
w += cnt[(s - 1 + k) % k];
if(w > s) break;
r = j - 1;
(ans += C(s - w + k - 1, k - 1) - C(s - w + r - 1, k - 1)) %= mod;
}
cout << (ans + mod) % mod << '\n';
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库