Codeforces Round #570 (Div. 3)部分题解(A ~ F)


前言

我把权游第4季看完都没想明白这个问题到底是啥意思。

随着人工智能的发展,在技术对人类本身的监控方面有哪些(建议字数:300字以上)

虽然我语文不是很行,但是也没到看不懂中文题目的程度:
虽然最后瞎编了一堆话交了上去,但是我还是对这个题的题意表示很纠结。

8说了,上主菜。


A - Nearest Interesting Number(暴力+水题)

比赛链接:https://codeforces.com/problemset/problem/1183/A

题目大意

给你一个数 x x x,找出离 x x x最近的一个数 y y y满足:
1. y > = x 1.y>=x 1.y>=x
2. y 的 每 个 数 位 之 和 可 以 整 除 4 2.y的每个数位之和可以整除4 2.y4

思路

x x x开始暴力所有的数,直到遇到一个满足条件的数为止。

AC代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=55000;

int main()
{
    
    
    int n;
    cin>>n;
    while(true){
    
    
        int m=n;
        int sum=0;
        while(m){
    
    
            sum+=m%10;
            m/=10;
        }
        if(sum%4==0){
    
    
            cout<<n<<endl;
            break;
        }
        n++;
    }
}

B - Equalize Prices (思维)

比赛链接:https://codeforces.com/problemset/problem/1183/B

题目大意

现在给你一个长度为 n n n的数组 a a a
你可以把数组 a a a中的任意一个数 a i a_i ai变成[ a i − k , a i + k a_i-k,a_i+k aik,ai+k]中的任意一个数字。但每个数字只能改一次。
例如 a i = 4 a_i=4 ai=4 k = 3 k=3 k=3,则 a i a_i ai可以改为 1 1 1~ 7 7 7中的任意一个数字。

现在问,你现在可不可以把数组 a a a中的所有数字改成同一个数字 B B B

不能就输出 − 1 -1 1,如果能则输出 B B B的最大值。

思路

一个很简单的思维题。

首先我们先想最简单的:数字 B B B存不存在?

我们只需要找到数组中最大的数 m a x x maxx maxx和数组中最小的数 m i n x minx minx
m i n x minx minx最大可以变成 m i n x + k minx+k minx+k m a x x maxx maxx最小可以变成 m a x x − k maxx-k maxxk.
如果此时最小的最大还是小于最大的最小,那么 B B B就肯定不存在了,输出 − 1 -1 1;否则就存在 B B B

那么最大的 B B B是多少呢?
m i n x + k minx+k minx+k

AC代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=150;
int a[maxn];
int main()
{
    
    
    int q,n,k;
    cin>>q;
    while(q--)
    {
    
    
        cin>>n>>k;
        for(int i=0;i<n;i++)
            cin>>a[i];
        sort(a,a+n);
        if(a[0]+k>=a[n-1]-k) cout<<a[0]+k<<endl;
        else cout<<"-1"<<endl;
    }
}

C - Computer Game (思维)

比赛链接:https://codeforces.com/problemset/problem/1183/C

题目大意

宿舍断电了, V o v a Vova Vova的电脑还有 k k% k的电量,但是他刚入手了一款非常好玩的游戏,于是他决定上号玩一把。

这个游戏有 n n n个关卡, V o v a Vova Vova作为一个游戏高手自然想要玩通关。关卡分为两种: a 和 b a和b ab

1.当 V o v a Vova Vova的电脑电量严格大于 a a a时,他可以玩一把 a a a类型的关卡,此时电量会减少 a a a
2.当 V o v a Vova Vova的电脑电量严格大于 b ( b < a ) b(b<a) b(b<a)时,他可以玩一把 b b b类型的关卡,此时电量会减少 b b b
3.当 V o v a Vova Vova的电脑电量小于 b b b时,他就没法玩游戏了。

V o v a Vova Vova想知道他能否在电脑歇菜之前通关这个游戏,不能输出 − 1 -1 1
如果可以, V o v a Vova Vova想知道他最多能玩几场 a a a类型的关卡,输出这个数量。

思路

彼时彼刻,恰如此时此刻,宿舍断电了,有点裂开。
一道有点难度的思维题,推了好一会才出的答案。

首先还是先判断最简单的:
从题目中可以看出 b < a b<a b<a,那么我们就看如果我们玩 n n n b b b类型的关卡电脑能否撑得住。
玩n场b类型的关卡需要的电量为 n ∗ b n*b nb,电脑电量为 k k k,则根据题目描述: n ∗ b < k n*b<k nb<k

接下来我们设可以玩 x 1 x_1 x1 a a a类型的关卡, x 2 x_2 x2 b b b类型的关卡,则有公式:

x 1 + x 2 = n x_1+x_2=n x1+x2=n
x 1 ∗ a + x 2 ∗ b < k x_1*a+x_2*b<k x1a+x2b<k

此时再根据 a > b a>b a>b可以推得:

x 1 ∗ ( a − b ) + ( x 1 + x 2 ) ∗ b < k x_1*(a-b)+(x_1+x_2)*b<k x1(ab)+(x1+x2)b<k

再结合 x 1 + x 2 = n x_1+x_2=n x1+x2=n,再次化简:

x 1 ∗ ( a − b ) + n ∗ b < k x_1*(a-b)+n*b<k x1(ab)+nb<k

x 1 < k − ( n ∗ b ) ( a − b ) x_1<\frac{k-(n*b)}{(a-b)} x1<(ab)k(nb)

再利用C语言中的 / / /是向下取整,所以 x 1 = k − ( n ∗ b ) ( a − b ) x_1=\frac{k-(n*b)}{(a-b)} x1=(ab)k(nb)

不过还有一个点:当 k − ( n ∗ b ) k-(n*b) k(nb)可以整除 ( a − b ) (a-b) (ab)时,代表电量是正好够的.
但实际上是没法完成的,因为你的用电量是要严格大于 k k k的,所以此时我们需要少玩一局 a a a类型的关卡( x 1 − − x_1-- x1)。

AC代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=150;
int main()
{
    
    
    int t;
    cin>>t;
    while(t--)
    {
    
    
        ll k,n,a,b;
        cin>>k>>n>>a>>b;
        if(k<=n*b) cout<<"-1"<<endl;
        else
        {
    
    
            ll x=(k-n*b)/(a-b);
            if((k-n*b)%(a-b)==0) x--;
            cout<<min(n,x)<<endl;
        }
    }
}

D - Candy Box (easy version) (魔鬼题+贪心)

比赛链接:https://codeforces.com/problemset/problem/1183/D

题目大意

你现在有 n n n个糖果,第 i i i个糖果的种类是 a i a_i ai
现在你想拿着你的糖果去送人。

你不喜欢把糖果混在一起,所以你都只给每个人一种不同于其他人的糖果。
你希望送给每个人的糖果的数量都不同,你现在想知道你最多能送出多少糖果。

思路

这个题的时间复杂度很魔鬼,给了 3 s 3s 3s,却在那里卡死你的memset,只要用这个初始化数组就会 T T T

很简单的一道贪心题。
我们先把所有糖果按照种类统计一下:

for(int i=0;i<=n;i++)
	a[i]=0;          //a[i]:种类为i的糖果的数量
for(int i=0;i<n;i++){
    
    
	int x;
	cin>>x;
	a[x]++;
}

接下来从大到小排个序,然后贪心模拟整个过程就可以。

每次记录上次送出的糖果数量 p r e pre pre

如果此次要送的糖果的数量小于上次的数量 p r e pre pre,那我们就全部送出去,并更新上一次的数量 p r e pre pre
否则我们就送 p r e − 1 pre-1 pre1个,并更新上一次的数量 p r e pre pre

AC代码

///memset会T
///不是3s吗?
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+100;

int a[maxn];

int main()
{
    
    
    int t;
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
    
    
        int n;
        cin>>n;
        for(int i=0;i<=n;i++)
            a[i]=0;
        for(int i=0;i<n;i++){
    
    
            int x;
            cin>>x;
            a[x]++;
        }
        sort(a+1,a+n+1,greater<int>());
        ll ans=a[1];
        int pre=a[1];
        for(int i=2;i<=n;i++){
    
    
            if(a[i]==0) break;
            if(a[i]<pre){
    
    
                ans+=a[i];
                pre=a[i];
            }
            else{
    
    
                ans+=pre-1;
                pre--;
            }
            if(pre==0) break;
            //cout<<"ans="<<ans<<endl;
        }
        cout<<ans<<endl;
    }
}

E - Subsequences (easy version) (BFS)

比赛链接:https://codeforces.com/problemset/problem/1183/E

题目大意

给一个字符串 s s s,每次你可以删除任意一个字符形成一个新串 s ′ s' s

问字符串 s s s是否可以生成 k k k个不同的字符串。
不可以的话输出 − 1 -1 1,可以的话输出生成 k k k个不同的字符串最少要删除多少个字符。

思路

暴力就可以,直接写一个 B F S BFS BFS爆搜出所有结果,用 m a p map map来进行标记。

AC代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+100;

string ss;
map<string,int> mp;
int n,k;
int bfs()
{
    
    
    queue<string> q;
    q.push(ss);
    mp[ss]=1;
    int cnt=0;
    while(!q.empty()&&k){
    
    
        string str=q.front();
        q.pop();
        k--;
        cnt+=n-str.size();
        for(int i=0;i<str.size();i++)
        {
    
    
            string s1=str.substr(0,i)+str.substr(i+1,str.size()-i-1);
            if(mp[s1]==0){
    
    
                mp[s1]=1;
                q.push(s1);
            }
        }
    }
    if(k) return -1;
    else return cnt;
}
int main()
{
    
    

    cin>>n>>k;
    cin>>ss;
    int ans=bfs();
    cout<<ans<<endl;
}

F - Topforces Strikes Back(数学+贪心)

比赛链接:https://codeforces.com/problemset/problem/1183/F

题意

给出由n个数字构成的数组a。

你可以在数组a中寻找最多三个数进行求和。
你找的数需要满足:彼此之间不能被整除。
例如,你找到了 a 、 b 、 c ( a < b < c ) a、b、c(a<b<c) abc(a<b<c),则它们需要满足:c不能整除a与b,b不能整除a

问:这个和最大是多少?

思路

这个题稍微有些难度,但还是比较简单的。

首先看完题之后我们需要知道:原本的数组并不能直接用,需要去重(相同的数字互相整除)。

去重的方法有很多, s e t , u n i q u e set,unique setunique等等。
我这里用的是unique,这是我之前看大佬题解时看到的一种去重,感觉很不错。

vector<ll> arr;
for(int i=1; i<=n; i++)
{
    
    
   cin>>x;
   arr.push_back(x);
}
sort(arr.begin(),arr.end());
arr.erase(unique(arr.begin(),arr.end()),arr.end());

接下来我们开始枚举 a a a的值。

由于是要求最大值,所以我们 a , b , c a,b,c abc都是按照最大值去取。
枚举的代码是一个 O ( n 3 ) O(n^3) O(n3)的时间复杂度,但是由于每次我们都是贪心处理(即一旦找到合适的值就一定是这个 a a a能够达到的最大值,不再去考虑别的组合),所以实际上没有这么拖时间。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+100;

int main()
{
    
    
    int t;
    cin>>t;
    while(t--)
    {
    
    
        ll n,x;
        cin>>n;
        vector<ll> arr;
        for(int i=1; i<=n; i++)
        {
    
    
            cin>>x;
            arr.push_back(x);
        }
        sort(arr.begin(),arr.end());
        arr.erase(unique(arr.begin(),arr.end()),arr.end());
        int len=arr.size();
        ll ans=0;
        for(int i=len-1; i>=0; i--)
        {
    
    
            ans=max(ans,arr[i]);
            //cout<<arr[i]<<" "<<endl;
            for(int j=len-1; j>i; j--)
            {
    
    
                if(arr[j]%arr[i])
                {
    
    
                    ans=max(ans,arr[i]+arr[j]);
                    //cout<<arr[i]<<" "<<arr[j]<<" ";
                    for(int k=j-1; k>i; k--)
                        if(arr[j]%arr[k]&&arr[k]%arr[i])
                        {
    
    
                            ans=max(ans,arr[i]+arr[j]+arr[k]);
                            //cout<<arr[i]<<" "<<arr[j]<<" "<<arr[k]<<endl;
                            break;
                        }
                    break;
                }
            }
            //cout<<endl;
        }
        cout<<ans<<endl;
    }
}

感谢阅读,希望能对你产生一点用处。

在这里插入图片描述

"这是很久很久以前的事了,是我们的父母和前人做的事。"
"我们不过是他们的牵线木偶,"
"直到某天我们自己的孩子连上我们做的线,在我们的牵引下跳舞。"

吾日三省吾身:日更否?刷题否?快乐否?
更新了,但不是日更;已刷;happy!
吾心满意足。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45750296/article/details/120641843