首页 > 其他分享 >[CF1188E] Problem from Red Panda 题解

[CF1188E] Problem from Red Panda 题解

时间:2024-11-14 23:08:37浏览次数:1  
标签:int 题解 bound ge CF1188E 序列 操作 Problem mod

[CF1188E] Problem from Red Panda 题解

考虑每个位置的操作次数 \(c_i\),不难发现,\(i\) 气球最后的颜色个数 \(d_i\) 是 \(a_i + c_ik-\sum c_i\),如果存在 \(\forall c_i > 0\),那么我们总是可以把所有气球少操作一次,这样上式不变,不影响最后的序列,下文所有的操作序列都假设 \(\min c_i = 0\)。

考虑原序列和操作序列的关系,断言:操作序列(假设后)和原序列一一对应

证明:
形式化地说,假设有操作序列 \(A, B, |A| = |B|\),最后得到的气球序列为 \(ta, tb\),欲证 \(A = B \Longleftrightarrow ta = tb\)。

充分性是显然的,论证必要性:考察气球序列中的位置 \(i\),有 \(ta_i = tb_i\),有 \(a_i + A_ik-|A| = a_i + B_ik - |B|\),因为 \(|A| = |B|\),所以 \(A_i = B_i\),证毕。

得到这个之后,我们只需要计数操作序列即可,并且不用管算重的问题。

发现操作总数 \(s\) 总是 \(\le \max a_i\),这是因为如果 \(s> \max a_i\),再根据 \(\min c_i = 0\) 的假设,总是存在一个 \(i\),使得 \(d_i < 0\),这非法,所以可以考虑枚举 \(s\)。

考虑操作序列合法的充要条件,首先显然有 \(\forall d_i = a_i + c_ik-s \ge 0\),得到 \(c_i\ge \lceil \dfrac{s - a_i}{k} \rceil\),设这个下界是 \(bound_s(i)\),此时我们有 \(s =\sum c_i \ge \sum bound_s(i)\),为了保证任意时刻都存在合法的操作,另一个条件是 \(\forall t\le s, t\ge\sum bound_t(i)\)。

证明:
必要性显然。

关于充分性,考虑构造一组合法操作序列,不难发现,随着 \(t\) 的增大,\(bound_t(i)\) 一定单调不降,对于一个时刻,一定有一部分操作是必须要放到一些位置上,为了满足下界的需求,剩余有一些操作是可以随便放的,所以每次 \(bound_t(i)\) 的增加时,把本来可以随便放的操作放到增加的 \(bound_t(i)\) 的位置即可,因为有 \(t\ge\sum bound_t(i)\),所以总是能够满足 \(bound_t(i)\) 的需求。

根据不等式 \(c_i\ge \lceil \dfrac{s - a_i}{k} \rceil\),如果 \(a_i \ge s\),则 \(i\) 位置不需要操作也行,它的 \(bound_i = 0\),而 \(a_i < s\) 的部分就有操作的需求,不妨假设 \(a\) 不降,随着 \(s\) 的增加,有操作需求的位置的分界线 \(r\) 会单调地向右移动,用双指针维护这个分界线,同样的,我们也可以维护 \(w = \sum bound_t(i)\),因为每次变化的只有 \(s - 1\equiv a_i\pmod k\) 的那些 \(i\),它们的下界会增加 1,用桶维护 \(w\)。

剩下的部分是一些简单的组合计数,需要满足:前 \(r\) 个位置的操作次数 \(\ge bound_s(i), i\le r\),后 \(k - r\) 个位置中至少有一个位置操作次数是 0(需要满足一开始的假设才不会算重),现在有 \(s\) 个操作次数,问有几种分配操作次数的方案。

容斥后 \(k - r\) 至少有一个 0,然后就是经典小球盒子插板法解决的问题了。

这里的答案就等于:

\[\binom{n - w + k - 1}{k - 1} - \binom{n - w + r - 1}{k - 1} \]

需要注意的是,如果一个时刻 \(s < w\),直接结束枚举,这是为了满足充要条件 2。

代码实现

#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;
}

标签:int,题解,bound,ge,CF1188E,序列,操作,Problem,mod
From: https://www.cnblogs.com/MoyouSayuki/p/18547089

相关文章

  • [JXOI2017] 加法 题解
    [JXOI2017]加法最小值最大,一眼二分。贪心地,每次尽量对包含当前序列最小值的区间做加法操作,也就是说,对于当前二分的答案\(x\),任何的\(A_i<x\)都需要被操作。从左到右地考虑答案。我们认为当前点之前的所有值都已经满足条件,于是我们只需考虑每次区间对当前点之后答案造成的贡......
  • 题解:P7836 「Wdoi-3」夜雀 collecting
    题解摘自做题记录。分析数据范围明显得要让我们分开搞。【Sub2】应该是暴力。这里有个主体思路,我们完全可以贪心地将当前背包里的食材删掉,直到每种出现过的食材数量刚好为\(1\)。因为我们保留更多的是没有用的。那么我们就可以用二进制数表示\(x\)种食材的出现状态了。同......
  • 【题解】CF1982
    A考虑两队的领先情况改变,那么一定有某一时刻两队的比分相等于是首先检查最开始的领先队伍,再检查现在的领先队伍,如果前后不同,则\(YES\),否则\(NO\)B注意到当\(x=1\),则会进入循环,手模一下发现\(ans=k\%(y-1)+1)\)现在的问题是:什么时候\(x=1\)?直接手动模拟即可,不难证明时......
  • Intellij IDEA如何设置中文版?安装中文汉化包插件?失败问题解决!
    前言大家好,我是小徐啊。IntellijIDEA默认是英文的操作界面,因为是外国人开发的嘛~对于英文好一点的同学来说,英文就英文吧,但对于英文比较差的同学,就还是希望能够汉化一下,变成熟悉的中文。今天小徐就来介绍下如何在IDEA中安装汉化插件,以及在这过程中,我遇到的奇怪问题,以及最后如何......
  • P8099 [USACO22JAN] Minimizing Haybales P 题解
    好题图论的难点在于建图~首先我们关注到如果两个草堆之间的差大于K,那么他们的位置就是固定的,就相当于给了一些限制,这就是很经典的连边然后拓扑排序。其实你是不是可以直接从小的向大的连边(我没试)然后再做排序。这一部分代码(粗略验证正确性,赶着写的,可能比较一言难尽)#include<bi......
  • 【考试题解】NOIP2024(欢乐)加赛3
    目录A.SakurakoandWater题目内容思路代码B.BinomialCoefficients,KindOf题目内容思路代码C.QED'sFavoritePermutation题目内容思路代码D.CardGame题目内容思路代码E.LongWaytobeNon-decreasing题目内容思路代码F.ManyGames题目内容思路代码A.SakurakoandW......
  • COCI19-20#6 Trener题解
    COCI19-20#6Trenerlink一道水题(我真是太弱了啊啊啊啊。众所周知,看到这个题立刻知道他是要选名字长度为$1$到$N$的,而我们知道他每一个名字,所以可以直接用字符哈希去做,因为他每一个名字的字符数是上一层名字的字符数加一,所以对于哈希每个字符串只需要跑三次,分别是自己的这......
  • 【题解】洛谷P11186: 三目运算
    不好玩!!!这是个树形结构,直接暴力模拟,但过不去,但是需要发现答案是个区间,我们对字符串处理时记录最大值最小值,然后到叶子节点时我们将此时的区间存起来,查询时直接二分查询这个数对于的区间就可以了。总结:不好玩!!!#include<bits/stdc++.h>usingnamespacestd;#definelllonglon......
  • 每日一题:https://www.luogu.com.cn/problem/P2249
    includeusingnamespacestd;intmain(){intp,sum;cin>>p>>sum;intarr[p];for(inti=0;i<p;i++){cin>>arr[i];}for(inti=1;i<=sum;i++){intmubiao;intmin=0;intmax=p-1;cin>>mubiao;for(;......
  • 每日一题 :https://www.luogu.com.cn/problem/P2249
    includeusingnamespacestd;intmain(){intp,sum;cin>>p>>sum;intarr[p];for(inti=0;i<p;i++){cin>>arr[i];}for(inti=1;i<=sum;i++){intmubiao;intmin=0;intmax=p-1;cin>>mubiao;for(;;){if(arr[0]mubiao){printf(......