HRBU_20211006训练

目录

A - Nearest Interesting Number

题意:

做法:

B - Equalize Prices

题意:

做法:

C - Computer Game

题意:

做法:

D - Candy Box (easy version)

题意:

做法:


A - Nearest Interesting Number

题意:

给定你一个数n,这个数字n一定满足它的数位和一定是3的倍数,现在给定一个完美数的定义:如果一个数字的数位和能被4整除,那么这个数字就是完美数,现在要求你算出最小的大于给定数字n的完美数

做法:

数位和的判断很简单,取余除10即可,找最小的完美数只需要在n+1的基础上进行循环判断即可,特判点:这个数字n本身的数位和即是4的倍数,所以对于n就得判断一次

WA了两发的我是FW!

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=1e5+10;
int t,n,m,k;
string s;

int main()
{
    ios::sync_with_stdio(false);
    int a;
    while(cin>>a)
    {
        int tmp=0,n=a;
        while(a>0)
        {
            tmp+=a%10;
            a/=10;
        }
        if(tmp%4==0)
            cout<<n<<endl;
        else
        {
            for(int i=n+1;;i++)
            {
                int tt=i,ans=0;
                while(tt>0)
                    ans+=tt%10,tt/=10;
                if(ans%4==0)
                {
                    cout<<i<<endl;
                    break;
                }
            }
        }
    }
    return 0;
}

B - Equalize Prices

题意:

给定一个有n个数字的数组以及一个数字k,问能否找到一个数字B,B满足在数组中的任意一个数字±k的区间内,即B∈[a[i]-k,a[i]+k],如果不存在这样的数字B就输出-1

做法:

设想一下,要满足在一个数组内部所有数字的条件区间内,那么我们去两个极值,一个最大一个最小,这两个值算出来的值,不就是这个数组最大的范围区间的中间值,然后我们再判断这个值是否满足<=min+k&&>=max-k,然后因为题目中要求要是存在多个答案输出最大值,SO,min+k永远大于max-k,所以我们只需要把求出来的数字和min+k取个最大值就好了!

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=1e5+10;
int t,n,m,k;
string s;

int main()
{
    ios::sync_with_stdio(false);
    int t,k,a[110];
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+n+1);
        int tmp=(a[1]+a[n])/2;
        if(a[1]+k>=tmp&&a[n]-k<=tmp)
            cout<<max(tmp,a[1]+k)<<endl;
        else
            cout<<"-1"<<endl;
    }
    return 0;
}

C - Computer Game

题意:

你拥有一台笔记本,这台笔记本拥有k的电量,但是你还想玩n把游戏(再来亿把!!)你有两种选择:1、你可以不充电每玩一把游戏需要消耗a的电量。2、你可以边充电边玩,每玩一把需要消耗b的电量(别问为啥充电还掉电,问就是题目要求)问你最多能玩几把游戏(最多就是玩n把!这很重要的

做法:

让我们来做一个比较离谱的算术

首先假设我们可以使用第一个方法玩x1次也就是x1*a,然后我们接着用第二个方法玩x2次也就是x2*b,这里为啥是分开算的呢,因为题目说明了a一定大于b,所以必然存在你玩了x1把之后剩余的电量还可以让你用第二个方法玩,因此设置两个变量。由此我们可以得出第一个表达式:x1*a+x2*b<k(不能=,因为第三个条件说明了k只要小于等于a,b中任意一个,就不可以再继续),接着a<b -> a-b<0,然后a-b<0代入x1*a+x2*b<k

我们就得到了x1*(a-b)+x2*b<k为了保持原式子的完整性,添加x1*b

SO,最后的表达式就变成了x1*(a-b)+(x2+x1)*b<k

此时题意里的强调就起到作用了,因为这里x1,x2是一种最优解的条件,那么意味着x1+x2=n(谁不想多玩点呀是吧)

所以式子再次变化x1*(a-b)+n*b<k  -> x1<(k-n*b)/(a-b)

所以最优解就是这么个情况,注意C++语言除法默认向下取整,然而这里是<而不是<=因此,当右边能够整除时,这个数字-1才是我们的正确答案。以及一个特殊情况:当你用第二种方法去玩n把游戏时,电量根本不足以支撑你的任意一把游戏,你就得直接输出-1(别问怎么知道的,问就是被题目样例给坑了)

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=1e5+10;
string s;

int main()
{
    ios::sync_with_stdio(false);
    ll t,k,a,b,n;
    cin>>t;
    while(t--)
    {
        cin>>k>>n>>a>>b;
        ll x=(k-n*b)/(a-b);
        if((k-b*n)<=0)
        {
            cout<<-1<<endl;
            continue;
        }
        if((k-n*b)%(a-b)==0)
            x--;
        cout<<min(x,n)<<endl;
    }
    return 0;
}

D - Candy Box (easy version)

题意:

你一共有q个糖果,这些糖果中有几种种类(种类数未知)当你要把这些糖果送给别人时,你可以取出同一种类的所有糖果(没说一定要取完!),但是当你第二次送给别人糖果时,你取出的这个种类的糖果数不能和你上一个送出的糖果数相同,问你最多能送出多少个糖果

做法:

排序加贪心,暴力跑就完了,从最大的个数开始送,送完一个就判断下一个值,要是这个值和刚刚的一样,那就少拿一个!物尽其用!

注意数组初始化的时候,不能全部初始化,会被卡死在第25个点

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=2e5+10;
string s;

int main()
{
    ios::sync_with_stdio(false);
    int t,n,num[maxn],maxx=0;
    cin>>t;
    while(t--)
    {
        maxx=0;
        cin>>n;
        for(int i=1;i<=n;i++)
            num[i]=0;
        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            num[x]++;
            maxx=max(x,maxx);
        }
        sort(num+1,num+maxx+1);
        int tmp=num[maxx],ans=0;
        for(int i=maxx;i>=1;i--)
        {
            if(num[i]<=0||tmp<=0)
                break;
            if(tmp>num[i])
                tmp=num[i];
            ans+=tmp;
            tmp--;
        }
        cout<<ans<<endl;
    }
    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值