Codeforces Round #570 (Div. 3)简要题解

A. Nearest Interesting Number

分析:随便写写就可以了。

#include "bits/stdc++.h"
using  namespace std;
int getsum(int a){
    int res = 0;
    while(a){
        res+=a%10;
        a/=10;
    }
    return res;
}
int main(){
    int n;
    cin>>n;
    while(getsum(n)%4!=0)n++;
    cout<<n<<endl;
}

B. Equalize Prices

分析:找出最小值和最大值,两者的差小于等于K*2就OK,大于就输出-1。因为要求最大的,输出最小值+k就可以了。

#include "bits/stdc++.h"
using  namespace std;
int a[104];
int main(){
    int q;
    cin>>q;
    while(q--){
        int n,k;
        cin>>n>>k;
        for (int i = 0; i < n; ++i) {
            scanf("%d",&a[i]);
        }
        sort(a,a+n);
        int maxi = a[n-1],mini=a[0];
        if(maxi-mini>2 * k)puts("-1");
        else printf("%d\n",mini+k);
    }
}

C. Computer Game

分析:直接算一下就可以了,我这里写的不需要动脑子的二分。

#include "bits/stdc++.h"
using  namespace std;
int a[104];
int main(){
    int q;
    cin>>q;
    while(q--){
        long long k,n,a,b;
        scanf("%lld%lld%lld%lld",&k,&n,&a,&b);
        long long ans = -1;
        long long l = 0, r = n;
        while(l<=r){
            long long mid = (l+r)>>1;
            if(mid*a+(n-mid)*b<k){
                ans = mid;
                l = mid+1;
            }
            else r=mid-1;
        }
        printf("%lld\n",ans);
    }
}

D. Candy Box (easy version)

分析:记录一下每种糖果的个数,然后排个序,从最多的糖果开始选,如果有相等的,减1就可以了,这样可以保证size最大。

#include "bits/stdc++.h"
using  namespace std;
int a[200004];
int main(){
    int q;
    cin>>q;
    while(q--){
        int n;
        scanf("%d",&n);
        for (int i = 0; i <= n; ++i) {
            a[i]=0;
        }
        int x;
        for (int i = 0; i < n; ++i) {
            scanf("%d",&x);
            a[x]++;
        }
        sort(a+1,a+1+n);
        int ans = a[n];
        for (int i = n-1; i >= 1; --i) {
            if(a[i]<a[i+1])ans+=a[i];
            else {
                a[i]=a[i+1]-1;
                if(a[i]<0)a[i]=0;
                ans+=a[i];
            }
        }
        printf("%d\n",ans);
    }
}

E. Subsequences (easy version)

分析:直接找出所有子序列然后丢进set里,这是最暴力的想法,并且这里K只有100,所以是可行的。因为要求cost最小,所以从长度最长的开始,一个一个字符的删除,如果没有就丢进set和队列里,跑一遍就可以了。

#include "bits/stdc++.h"
using  namespace std;
int a[200004];
int main(){
    int n,k;
    cin>>n>>k;
    string s;
    cin>>s;
    set<string>se;
    int ans = 0;
    queue<string>q;
    q.push(s);
    se.insert(s);
    while (!q.empty()){
        if(se.size()==k)break;
        s = q.front();q.pop();
        for (int i = 0; i < s.size(); ++i) {
            string ts = s;
            ts.erase(i,1);
            if(!se.count(ts)){
                se.insert(ts);
                ans += n- ts.size();
                q.push(ts);
            }
            if(se.size()==k)break;
        }
 
    }
    if(se.size()==k)printf("%d\n",ans);
    else printf("-1");
}

F. Topforces Strikes Back

分析:首先枚举第一个数,然后对于这个数的答案就确定了,把与x冲突的去掉,把最大的作为y,再把与y冲突的去掉,剩下最大的作为z。然后我们就可以开始暴力剪枝了,因为是找最大的,然后从大到小排个序,然后写3个for+剪枝,由于某种原因,大概3个for是跑不满的,复杂度O(能过)。

#include "bits/stdc++.h"
using namespace std;
int a[200004];
bool cmp(int a,int b){return a>b;}
int main(){
    int t;
    cin>>t;
    while (t--){
        int n;
        scanf("%d",&n);
        for (int i = 0; i < n; ++i) {
            scanf("%d",&a[i]);
        }
        sort(a,a+n,cmp);
        n=unique(a,a+n)-a;
        int ans = a[0];
        for (int i = 0; i < n; ++i) {
            bool ok = 0;
            for (int j = i+1; j < n; ++j) {
                if(a[i]%a[j]==0)continue;
                ans = max(ans,a[i]+a[j]);
                for (int k = j+1; k < n; ++k) {
                    if(a[i]%a[k]==0 || a[j]%a[k]==0)continue;
                    ans = max(ans,a[i]+a[j]+a[k]);
                    ok=1;
                    break;
                }
                if(ok)break;
            }
        }
        printf("%d\n",ans);
    }
}

G. Candy Box (hard version)

分析:D题plus。多了一个参数,相当于对两个关键字a,b排序。但是这里直接排序是不可以的,因为选了一种糖果后,如果还有其他种类的糖果的数量和它相等,那么需要将这些糖果的第一关键字减1,这里就乱序了。

那么我们可以开一个multiset,用来存当前数量的糖果的第二关键字,找出最大的一个erase掉,剩下的作为下次选糖果的备选。

#include "bits/stdc++.h"
using  namespace std;
struct node
{
    int num1,num2;
    bool friend operator < (node a,node b){
        if(a.num1==b.num1)return a.num2<b.num2;
        else return a.num1<b.num1;
    }
}a[200004];
int main(){
    int q;
    cin>>q;
    while(q--) {
        int n;
        scanf("%d", &n);
        int x, y;
        for (int i = 0; i <= n; ++i) {
            a[i].num1 = 0;
            a[i].num2 = 0;
        }
        for (int i = 0; i < n; ++i) {
            scanf("%d%d", &x, &y);
            a[x].num1++;
            a[x].num2 += y;
        }
        sort(a+1,a+1+n);
        multiset<int>s;
        int last = a[n].num1;
        int ans1 = 0,ans2 = 0;
        for (int i = n; i >= 0; --i) {
            if(a[i].num1==last){
                s.insert(a[i].num2);
            }
            else {
                i++;
                last--;
                if(s.size()>0){
                    ans1 += last+1;
                    ans2 += min(last+1,*(--s.end()));
                    s.erase(--s.end());
                }
                else continue;
            }
        }
        printf("%d %d\n",ans1,ans2);
    }
}

H. Subsequences (hard version)

留坑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值