【题解】第七次测试赛题解

A coins

You have unlimited number of coins with values 1,2,…,n You want to select some set of coins having the total value of S. It is allowed to have multiple coins with the same value in the set. What is the minimum number of coins required to get sum S?

题目大意:有面额为1~n的硬币,每种硬币都有无限个,问用多少硬币能凑齐总价值S。

提示:签到题

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
long long a,b;
    cin>>a>>b;
if(b <= a)
    cout<<1;
else if(b % a == 0)
    cout<<(b / a);
else cout<<(b / a + 1);
return 0;
}

B Views Matter

原题传送门

大概题意:给你 n 堆方块,此时初始情况会有一个俯视图和一个侧视图,问最多能抽取多少方块而不会改变原来的俯视图和侧视图,方块之间没有重力。

我想我应该讲的足够清楚,这里把课件里的几张图在拿给大家:(红色的是要保留的,白色的是可以拿掉的)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
long long sum;
long long tot;
long long k=1;
long long a[100005];
int n,m;
int main()
{
    cin>>n>>m;
for(int i = 0; i < n; i++)
{
scanf("%d",&a[i]);
        sum += a[i];      //记录方块总数
}
sort(a,a+n);        //排序
if(n == 1)
    cout<<0;            //如果只有一排的话,直接输出0
else {
for(int i = 0;i < n; i++)
{
if(i == n-1)      //最后一排特判一下,把之后的全部加上
{
if(a[i] <= k)
            tot++;
else tot += (a[i] - k + 1);
break;
}
if(a[i] >= k)
{
            k++;
            tot++;
}
else tot++;
}
    cout<<sum - tot;      //用总数减去要保留的就是所求结果要拿走的
}
return 0;
}
//k是我讲的现在考虑放在第几行

C Vasya and Book

原题传送门

此题题意大家都懂,做不出来可能细节处理不是很好。这里简而治之,无非三种情况

x能直接翻到y((y-x)%d==0)
x经过1翻到y((y-1)%d==0)
x经过n翻到y((n-y)%d==0)
x既能经过1翻到y,又能经过n翻到y,取两者步数最小值即可

细节处理见代码:

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int t;
 cin>>t;
while(t--)
{
int n,x,y,d;
  cin>>n>>x>>y>>d;
if(abs(x-y)%d!=0&&(y-1)%d!=0&&(n-y)%d!=0)//如果条件都不满足,直接输出-1
  cout<<-1<<endl;
else if(abs(x-y)%d==0)//注意一点x不一定比y小,所以取绝对值
  cout<<abs(x-y)/d<<endl;
else if((y-1)%d==0&&(n-y)%d==0)//如果同时满足后两种情况,取最小值
  cout<<min(((x-1)/d+1+(y-1)/d),((n-x)/d+1+(n-y)/d))<<endl;
else if((y-1)%d==0)
  cout<<(x-1)/d+1+(y-1)/d<<endl;
else if((n-y)%d==0)
  cout<<(n-x)/d+1+(n-y)/d<<endl;
}
return 0;
}

D Vova and Trophies

原题传送门

此题我的方法是枚举每个三元组,我所定义的三元组是连续的三个S所夹的中间部分,比如说:

SGGSGGS 这就是一个三元组,

你想,如果你找得到一个三元组(以刚才为例)那么这个组的最长连续G串的长度是多少?两种情况:

如果这个三元组之外没有G的存在,那么这个三元组连续G串的长度就是4(中间的S与最后一个G替换)
如果这个三元组之外还有G的存在,那么我们肯定会拿外边的G与这个三元组中间的S替换,而这个三元组连续G串长度变成了5

只要仔细想想就会发现,这个规律是题目通用的,问题在于我们找全题目给的串的所有三元组就行了

有同学会提出来如果串中如果是这样GGGSGGSSGGGG,我们找到只有一个三元组,那其它的G 就访问不到了,怎么办?

我给出的答案是在题目给我们指定的串之后(比如GGGSGGSSGGGG)我们完全可以在初始串的两边分别虚拟上两个S,这样的话所有的G都被包含在三元组里了

几个关键点:
如果给的初始串中一个S都没有,那么直接输出n
我们对于每个三元组要判断是否三元组之外有没有G,难道要遍历嘛?我的方法是就S的总个数,还有当前三元组的长度,还有总的串的长度其中的加加减减关系来判断
如果总的串的长度=这个三元组的长度+S的总个数-3那么此三元组之外肯定没有G的存在,不等于的话肯定有G的存在(想一想为什么)

问题到这基本就解决完毕:

这里我用vector来预处理每个S的位置i,用数组也可以,但要开个变量保留总的S的个数

PS 我这里不知道csdn又出现了什么bug,这个题的代码粘不上,粘上就卡死,这里我不直接放在这里,如果要看此题代码移步我的下一篇博客代码

还要吐槽一下,这代码粘贴缩进有问题啊!有问题啊!有问题啊!

感谢阅读,欢迎评论以及私聊我意见和建议

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值