原题链接:蓝桥杯2022年第十三届决赛真题-卡牌
整体思路:
将现有牌数进行排序,先记录下此时最小牌数min,
那么想要增加一套牌,牌数最小的数字必须加一张手写牌
随后把牌数更新,同时判断后续牌数有没有也是min的;
如果没有就说明本次加入手写牌后整体就增加一套牌
如果有(例如初始牌数都是一样的)那就不急着增加套牌数,对这个牌进行同样的操作
注意事项:开long long
参考代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5 + 10; ll a[N];//a[i]是指 第i种牌最多能手写 a[i]张 //利用 multimap 以牌数进行排序,key会出现重复的情况 multimap<int,int> p;//对组p<某号牌现有的牌数,这组牌的初始下标> 初始下标是为了后续访问a[i] ll n,m; //ans是记录利用手写牌所能增加的套牌数,sum是记录初始时有多少套牌数 //最终的数就是二者之和 ll ans = 0,sum = 0; void way(){//统计ans if(m<=0) return;//已经没有手写牌了,就返回 auto bg = p.begin();//bg指向当前最小牌数的pair对组 int min = bg->first;//记录最小值方便后续判断是否算得上增加了一套牌 int dex = bg->second;//拿到这组牌的初始下标,便于访问a[i]查看他最多能加入几张手写牌 if(a[dex]>0){//只有剩余纸张大于0(m>0前面已经判断)且这个号牌还能加入手写牌(a[i]>0) 才加入手写牌 a[dex]--;//还能加入的手写牌数减1 m--;//总的纸张数减1 int temp = min; temp++; //拿到他已有的牌数 加一张手写牌 p.erase(bg);//删除原来的数据 p.insert(pair<int,int>(temp,dex));//加入现在更新的数据 bg = p.begin();//重新让bg指向此时最小数牌的pair对组 } else {//无法再加入手写牌就返回 return; } if(bg->first!=min) {//现在的最小牌数跟加入手写牌前的最小牌数不同 ans++;//增加的这一张手写牌可以让套牌数加1 } way();//继续上述操作直到无法再加入手写牌 } void solve(){ //数据初始化 cin>>n>>m; for(int i=0;i<n;i++){ int j; cin>>j;//初始牌数,i为初始下标与a[i]对应 p.insert(pair<int,int>(j,i)); } sum = p.begin()->first;//拿到初始的套牌数 就是牌数最少的那个号牌的数量 for(int i=0;i<n;i++){ cin>>a[i];//a[i]记录对应牌的手写牌数量上限 } way();//统计手写牌的加入能增加几个套牌数---ans cout<<ans + sum;//总套牌数 = 初始套牌数 + 手写牌增加的套牌数 } int main(){ solve(); return 0; }
0.0分
3 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复