首页 > 其他分享 >CSP模拟 取模

CSP模拟 取模

时间:2024-09-09 21:35:40浏览次数:3  
标签:取模 int 差分 num MAXN 操作 CSP 模拟

最近开始写 CSP 模拟的题,实际上考的题一点也不 CSP

题意

有一个长度为 \(n\) 的序列 \(A\),\(0\leq A_i<k\),你可以每次选取一个区间,将区间内所有元素 \(+1\),然后将区间内所有元素对 \(k\) 取模。问最少几次操作可以把序列中所有元素都变为 \(0\)。

思路

假设现在有一个数列 \([2,3,1,0,3,2]\),\(k=4\),我们考虑如何将它变为 \(0\)。

发现每次操作后都要模 \(k\) 的限制非常烦,因此我们做一个转化,每次操作直接加,而“区间内所有元素等于 \(0\)” 转化为了 “区间内所有元素\(\bmod k=0\) ”。

以上图为例,最优的方案为 \((1,7),(2,6),(3,5),(4,4),(4,4)\),共五步,我们把表示“增加值”的序列 \(B\) 用橙色表示。

如果把整张图“倒过来”,如下图,我们惊喜地发现这是一个经典问题,求多少次区间加 \(1\) 能覆盖代表 \(B\) 的橙色部分。很显然,操作次数即为 \(B\) 的差分数组 \(B^d\) 中的 \(>0\) 的数之和。

并且我们发现 \(B_i=(k-A_i)+ck\),且 \(c\) 的取值只可能为 \(0\) 或 \(1\) 时才优,为什么?因为考虑初始时差分数组 \(B^d\) 中所有元素绝对值一定是 \(<k\) 的,那么 \(B_i\) 加一次 \(k\) 体现在 \(B^d\) 上便为 \(B^d_i+k,B^d_{i+1}-k\),可以发现此时 \(B^d_i\) 必为正数且 \(B^d_{i+1}\) 必为负数,那么再加由于 \(B^d_{i+1}\) 只会越来越负不计入答案,而 \(B^d_i\) 为正且越来越大,\(B^d\) 的正数和只会更大。

因此我们考虑找到最优的给 \(B_i\) 加 \(k\) 的方案,根据差分数组的性质,若 \(B\) 上有连续的一段区间 \([l,r-1]\) 都被加上 \(k\),则反映到 \(B^d\) 上为 \(B^d_l+k,B^d_r-k\),此时 \(B^d_l\) 必为正数,\(B^d_r\) 必为负数,假设原先 \(B^d_r\) 为正数,那么这个操作对答案的贡献为原先的 \(B^d_r\) 减去现在的 \(B^d_l\)。听到这 solution 大概已经浮出水面了:即遍历差分数组 \(B^d\),对于每个大于 \(0\) 的 \(B^d_i\),找它前面最小的 \(B^d_j\) 判断操作后能不能使得答案变得更小,贪心即可。

注意操作后 \(B^d_i\) 将会变成负数,它也可以和后面的其他 \(B^d_t>0\) 进行一次操作。这有点类似反悔贪心的思想:对于 \(j<i<t\),\(j\) 和 \(i\) 操作,\(i\) 再和 \(t\) 操作实际上等价于 \(j\) 和 \(t\) 操作,\(i\) 就被“反悔”掉了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int MAXN=1e7+5;
int n=0,k,a[MAXN],b[MAXN];
string num;
priority_queue<pii,vector<pii>,greater<pii>>pq;
int main(){
    freopen("modulo.in","r",stdin);
    freopen("modulo.out","w",stdout);
    ios::sync_with_stdio(false);
    cin>>k>>num;
    a[++n]=num[0]-'0';
    for(int i=1;i<num.size();i++){
        if(num[i]!=num[i-1])
            a[++n]=num[i]-'0';
    }
    for(int i=1;i<=n;i++){
        if(a[i]!=0) a[i]=k-a[i];
    }
    for(int i=1;i<=n;i++){
        b[i]=a[i]-a[i-1];
    }
    for(int i=1;i<=n;i++){
        if(b[i]<0) pq.push(make_pair(b[i],i));
        else if(b[i]>0){
            if(pq.empty()) continue;
            int id=pq.top().second;
            if(b[id]+k<b[i]){
                pq.pop();
                b[id]+=k;
                b[i]-=k;
                pq.push(make_pair(b[i],i));
            }
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        if(b[i]>0) ans+=b[i];
    }
    cout<<ans<<endl;
    return 0;
}

后记

CF有道题有点类似,实际上还要简单一点,CF1852C

标签:取模,int,差分,num,MAXN,操作,CSP,模拟
From: https://www.cnblogs.com/SkyNet-PKN/p/18405404

相关文章

  • 每日OJ_牛客_单词倒排(字符串模拟)
    目录牛客_单词倒排(字符串模拟)解析代码牛客_单词倒排(字符串模拟)单词倒排__牛客网时间限制:C/C++1秒,其他语言2秒空间限制:C/C++32M,其他语言64M题目描述:对字符串中的所有单词进行倒排。说明:1、构成单词的字符只有26个大写或小写英文字母;2、非构成单词的字符均视为单词......
  • “PLUS模型+“生态系统服务多情景模拟预测
    生态系统服务是人类直接或间接从生态系统中获得的惠益,在应对城市挑战和实施可持续发展方面发挥着至关重要的作用。随着全球城市化的快速发展, 频繁的人类活动导致了土地利用的快速变化,导致生态系统结构和功能的变化,影响生态系统服务的供应。因此,生态系统服务评估与未来城市土......
  • Prometheus的拉取模式与zabbix推送模式有何区别?各有什么优缺点?
    Prometheus的拉取模式与Zabbix的推送模式在监控数据收集和处理方式上存在显著区别。以下是它们的主要区别及各自的优缺点:1.数据收集模式Prometheus拉取模式:Prometheus定期从被监控的目标(如Exporter、应用程序等)主动拉取数据。每个目标都需要暴露一个HTTP接口,Prome......
  • 【洛谷 P1996】约瑟夫问题 题解(数组+模拟+循环)
    约瑟夫问题题目描述个人围成一圈,从第一个人开始报数,数到的人出列,再由下一个人重新从开始报数,数到的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰名小朋友,而该题是全部出圈。输入......
  • 小集训 CSP-S 模拟赛
    DAY1A.喜剧的迷人之处在于小思维题不必细讲B.镜中的野兽状压+容斥$gcd(x)+lcm(x)=m$,可以得知$gcd(x)$一定是m的因子,那么就可以枚举$gcd(x)$和$lcm(x)$。对于已经确定的一对$gcd(x)和lcm(x)$,将他们进行质因数分解,写成$\prod{p_{i}^{c_{i}}......
  • 基于Python的期货交易模拟系统
    基于Python的期货交易模拟系统。开发技术:PyCharm开发环境;Python语言;MySQL数据库;Django框架;B/S架构。项目内容:该系统从三个对象:由管理员和用户、期货公司来对系统进行设计构建。主要功能包括:个人信息修改,对用户信息、期货公司信息、期货投资、取消投资、风险控制、账户资金、......
  • Cesium 展示——静态水添加动态波纹,模拟真实水面效果
    文章目录需求分析材料准备根据几何实例创建贴地面图元将图元添加到集合需求分析材料准备首先我们需要准备水波的图片,放在最后大家自行......
  • 洛谷 P9754 [CSP-S 2023] 结构体 题解
    题目传送门洛谷博客CSDNCSP-S2023T3结构体题解基本思路本题主要考查编码能力,所以直接给出基本思路:由于可以递归式的创建元素,最多可以同时存在\(100^{100}\)个不同的基础类型的元素。即使算上最大地址的限制,元素的数量也能达到\(10^{18}\)。显然,依次构造每个元素,在空......
  • 2024.9.8 CSP-S 模拟赛
    T1现在你站在坐标轴的一个整点上,给你\(n\)种技能,每个技能是整数对\((p,c)\)的形式,学会它需要花费\(c\),但是学会了可以无限用。用的意思是可以向左或向右\(p\)个单位长度。求最小的学技能开销,使得你可以访问到坐标轴的所有整点。\(n\leq10^5,x\leq10^9\)随便玩了一下......
  • CSP 模拟 29
    T1不相邻集合做法一:设\(f_i\)表示到当前位置以\(i\)结尾的最长长度,\(s_i\)表示以\(i\)开头的最长长度。有\(a>b\Leftrightarrowf_a>f_b\Leftrightarrows_a<s_b\),有了这个性质就可以直接上线段树维护,时间复杂度\(\mathcal{O}(n\logn)\)。#include<bits/stdc++.h>ty......