专栏: 蓝桥杯——每日四道编程题(两道真题+两道模拟)
“蓝桥杯就要开始了,这些题刷到就是赚到”
₍ᐢ..ᐢ₎♡
另一个专栏: 蓝桥杯——每日四道填空题(两道真题+两道模拟题)
目录
专栏: 蓝桥杯——每日四道编程题(两道真题+两道模拟)
另一个专栏: 蓝桥杯——每日四道填空题(两道真题+两道模拟题)
第一道真题(2022年省赛): 最少刷题数
第二道真题(2022省赛):刷题统计
第三道模拟题(acwing):数的范围
第四道模拟题(2021年第三期模拟赛):时间显示
问题描述
小蓝老师教的编程课有 N 名学生, 编号依次是 1…N 。第 i 号学生这学期刷题的数量是 Ai 。对于每一名学生, 请你计算他至少还要再刷多少道题, 才能使得全班刷题比他多的学生数不超过刷题比他少的学生数。
输入格式
第一行包含一个正整数 N 。第二行包含 N 个整数:A1,A2,A3,…,AN.
输出格式
输出 N 个整数, 依次表示第 1…N 号学生分别至少还要再刷多少道题。样例输入
5 12 10 15 20 6
样例输出
0 3 0 0 7
评测用例规模与约定
对于 30% 的数据,1≤N≤1000,0≤Ai≤1000.对于 100% 的数据, 1≤N≤100000,0≤Ai≤100000.
这题就是考察我们处理问题的思维+二分就行了。(直接用lower_bound 和 upper_bound函数是真的爽,不过自己写也行,哈哈~)
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
这题首先要先将数据排序,然后二分查找到它的中间数据(节约时间),中间数据右边的就不用考虑了,左边的需要把刷题数增加到比中间数据多一个。 但是目前我们还没有考虑到部分刷题数相同的数据怎么处理的问题,很显然如果是数据 12 15 15 15 20
此时我们的中间数据是15(下标3),那么此时我们左边右边的都需要考虑了.
此时就要保持这个区间[l , r](l是第一个15的下标,r是最后一个15的下标)不变。就只需要讨论它的左边,还有区间里的元素就可以了。建议看代码来理解 ~
#include
using namespace std;
const int N = 1e5 + 100;
int n, a[N], b[N];
int main() {
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i], b[i] = a[i];
sort(b + 1, b + n + 1);
int mid = 1 + n + 1 >> 1;
int l = lower_bound(b + 1, b + n + 1, b[mid]) - b; //查找左区间l
int r = upper_bound(b + 1, b + n + 1, b[mid]) - b - 1; //查找右区间r
bool f = l - 1 > n - r ? true : false; //如果区间左边的数据个数已经大于区间右边的数据个数,
//那么只需要把刷题数增加到和中间数据相等就行了
//为啥不能条件等于,因为你把数据增加过去了,左边就少一个了,条件不满足了
for (int i = 1; i <= n; ++i) {
if (a[i] == b[mid]) { //讨论在区间里的元素
if (l - 1 >= n - r) cout << 0 << " " ;
else cout << 1 << " " ;
}
//讨论区间左边的值,右边不用考虑。
else if (f) cout << max(0, b[mid] - a[i]) << " " ; //这里的max函数主要给区间右边给0就行了
else cout << max(0, b[mid] - a[i] + 1) << " " ;
}
return 0;
}
问题描述
小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天 做 a 道题目, 周六和周日每天做 b 题目。请你帮小明计算, 按照计划他将在 第几天实现做题数大于等于 n 题?输入格式
输入一行包含三个整数 a, b 和 n .输出格式
输出一个整数代表天数。样例输入
10 20 99
样例输出
8
这题比上面那到题简单多了,但是数据范围很大,记得用long long
由于n的数据范围很大,所以得先计算一下需要几周,在计算还需要几天。
#include
using namespace std;
typedef long long LL;
LL a,b,n;
int main() {
cin>>a>>b>>n;
LL sum=a*5+b*2;//一周的做题数
LL t=n/sum;//需要t周(往下取整)
LL k=t*sum;//t周做了k个题目
if(k>=n) cout<=n ) cout<= n ) cout<= n) cout<= n) cout<= n) cout<= n) cout<= n) cout<
为了复习二分,我们手动写lower_bound 和 upper_bound函数。
#include
using namespace std;
const int N=1e5;
int n,q,a[N],k;
int main()
{
scanf("%d%d",&n,&q);
for(int i=0;i>1;
if(a[mid]>=k) y=mid;
else{
x=mid+1;
}
}
if(a[x] != k){
printf("-1 -1\n");
}else {
printf("%d ",x);
int x1=0 , y1=n-1;
while(x1>1; //这里避免死循环,要+1
if(a[mid]<=k) x1=mid;
else{
y1=mid-1; }
}
printf("%d\n",y1);
}
}
return 0;
}
【问题描述】
小蓝将自己的车停在路边,在同一天将车开走。给定停车时间和开走时间,请问小蓝停了多长时间?
【输入格式】
输入两行,第一行包含停车时间,第二行包含开走时间。
每个时间的格式为 HH:MM:SS,其中 HH 表示时,值为 0 到 23 的整数,如果小于 10 用 0 补齐两位;MM 和 SS 分别表示分和秒,值为 0 到 59 的整数,小于 10 时用 0 补齐两位。
【输出格式】
输出总共停车的时间,格式为 HH:MM:SS。
【样例输入】
08:58:10 17:20:31
【样例输出】
08:22:21
这题不是我摆烂,而是想复习一下时间的相关计算,即时、分、秒的转换。
这里输出的前导零,用c 的输出方式就可以了(占位符)。
#include
using namespace std;
int main() {
int begin, end, ans;
int hh, ff, ss;
scanf("%d:%d:%d", &hh, &ff, &ss);
begin = hh * 3600 + ff * 60 + ss;
scanf("%d:%d:%d", &hh, &ff, &ss);
end = hh * 3600 + ff * 60 + ss;
ans = end - begin;
printf("%02d:%02d:%02d\n", ans / 3600, (ans / 60) % 60, ans % 60);
return 0;
}