第十三届蓝桥杯C++组
题目 2693:
蓝桥杯2022年第十三届决赛真题-卡牌
题目描述
这天,小明在整理他的卡牌。
他一共有 n 种卡牌,第 i 种卡牌上印有正整数数 i(i ∈ [1, n]),且第 i 种卡牌 现有 ai 张。
而如果有 n 张卡牌,其中每种卡牌各一张,那么这 n 张卡牌可以被称为一 套牌。小明为了凑出尽可能多套牌,拿出了 m 张空白牌,他可以在上面写上数 i,将其当做第 i 种牌来凑出套牌。然而小明觉得手写的牌不太美观,决定第 i 种牌最多手写 bi 张。
请问小明最多能凑出多少套牌?
输入格式
输入共 3 行,第一行为两个正整数 n, m。
第二行为 n 个正整数 a1, a2, …, an。
第三行为 n 个正整数 b1, b2, …, bn。
输出格式
一行,一个整数表示答案。
样例输入
4 5
1 2 3 4
5 5 5 5
样例输出
3
提示
这 5 张空白牌中,拿 2 张写 1,拿 1 张写 2,这样每种牌的牌数就变为了 3, 3, 3, 4,可以凑出 3 套牌,剩下 2 张空白牌不能再帮助小明凑出一套。
对于 30% 的数据,保证 n ≤ 2000 ;
对于 100% 的数据,保证 n ≤ 2 × 10^5 ; ai , bi ≤ 2n; m ≤ n2 。
听典的一个题,直接二分就行了
#include <iostream>
#include<vector>
#include<map>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll N = 2e5 + 10;
const ll mod = 1e9 + 7;
ll a[N],b[N];
ll n,m;
bool check(ll mid){
ll sum=0;
for(int i=1;i<=n;i++){
if(a[i]<mid)
if(mid-a[i]<=b[i])
sum+=mid-a[i];
else
return false;
if(sum>m)
return false;
}
return true;
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int j=1;j<=n;j++)
cin>>b[j];
ll l=0,r=N*N;
while(l<r){
ll mid=l+r>>1;
if(check(mid))
l=mid+1;
else
r=mid;
}
cout<<r-1<<'\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}
题目 2694:
蓝桥杯2022年第十三届决赛真题-最大数字
题目描述
给定一个正整数 N。你可以对 N 的任意一位数字执行任意次以下 2 种操作:
-
将该位数字加 1。如果该位数字已经是 9,加 1 之后变成 0。
-
将该位数字减 1。如果该位数字已经是 0,减 1 之后变成 9。
你现在总共可以执行 1 号操作不超过 A 次,2 号操作不超过 B 次。
请问你最大可以将 N 变成多少?
输入格式
第一行包含 3 个整数:N, A, B。
输出格式
一个整数代表答案。
样例输入
123 1 2
样例输出
933
提示
对百位数字执行 2 次 2 号操作,对十位数字执行 1 次 1 号操作。
对于 30% 的数据,1 ≤ N ≤ 100; 0 ≤ A, B ≤ 10
对于 100% 的数据,1 ≤ N ≤ 10^17; 0 ≤ A, B ≤ 100
考虑数据范围,复杂度只和位数有关,首先贪心,尽量让前面的数变大,当然变大可以减法或者加法两种操作,因此复杂度大概在2^17左右,需要注意的地方就是如果减法剩余次数不能使得数字变大的话,就不需要进行减法操作。
#include <iostream>
#include<vector>
#include<map>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll N = 2e5 + 10;
const ll mod = 1e9 + 7;
ll ans=0;
void dfs(string s,int pos,int a,int b){
if(pos==s.size()||a==0&&b==0){
ll sum=0;
for(int i=0;i<s.size();i++)
sum=sum*10+s[i]-'0';
ans=max(ans,sum);
return ;
}
int d1='9'-s[pos],d2=s[pos]-'0'+1;
if(a>0){
string s1=s;
s1[pos]+=min(a,d1);
dfs(s1,pos+1,a-min(a,d1),b);
}
if(b>=d2){
string s1=s;
s1[pos]='9';
dfs(s1,pos+1,a,b-d2);
}
dfs(s,pos+1,a,b);
}
void solve()
{
string s;
int a,b;
cin>>s>>a>>b;
dfs(s,0,a,b);
cout<<ans<<'\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}
题目 2695:
蓝桥杯2022年第十三届决赛真题-出差
题目描述
A 国有 N 个城市,编号为 1 . . . N。小明是编号为 1 的城市中一家公司的员工,今天突然接到了上级通知需要去编号为 N 的城市出差。
由于疫情原因,很多直达的交通方式暂时关闭,小明无法乘坐飞机直接从城市 1 到达城市 N,需要通过其他城市进行陆路交通中转。小明通过交通信息网,查询到了 M 条城市之间仍然还开通的路线信息以及每一条路线需要花费的时间。
同样由于疫情原因,小明到达一个城市后需要隔离观察一段时间才能离开该城市前往其他城市。通过网络,小明也查询到了各个城市的隔离信息。(由于小明之前在城市 1,因此可以直接离开城市 1,不需要隔离)
由于上级要求,小明希望能够尽快赶到城市 N,因此他求助于你,希望你能帮他规划一条路线,能够在最短时间内到达城市 N。
输入格式
第 1 行:两个正整数 N, M, N 表示 A 国的城市数量,M 表示未关闭的路线数量
第 2 行:N 个正整数,第 i 个整数 Ci 表示到达编号为 i 的城市后需要隔离的时间
第 3 . . . M + 2 行:每行 3 个正整数,u, v, c,表示有一条城市 u 到城市 v 的双向路线仍然开通着,通过该路线的时间为 c
输出格式
第 1 行:1 个正整数,表示小明从城市 1 出发到达城市 N 的最短时间(到达城市 N,不需要计算城市 N 的隔离时间)
样例输入
4 4
5 7 3 4
1 2 4
1 3 5
2 4 3
3 4 5
样例输出
13
提示
路线 1:1 -> 2 -> 4,时间为 4+7(隔离)+3=14
路线 2:1 -> 3 -> 4,时间为 5+3(隔离)+5=13
对于 100% 的数据,1 ≤ N ≤ 1000 , 1 ≤ M ≤ 10000, 1 ≤ Ci ≤ 200, 1 ≤ u, v ≤ N, 1 ≤ c ≤ 1000
在以某个点为起点的边上加上延迟然后跑一遍最短路就可以了,注意cpp的堆是大根堆,又一次忘记开了,要是实际比赛这直接jiji
#include <iostream>
#include<vector>
#include<map>
#include<string>
#include<queue>
#include<algorithm>
using namespace std