Codeforces Round #437 (Div. 2)-A-B-C-E

本文解析了CodeForces比赛867中的四道题目,包括简单的字符串处理、找规律解决组合计数问题、披萨选择的最优解策略及一道智商题的巧妙解法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://codeforces.com/contest/867

只补了四道题。

A题:简单模拟即可,分别计算S->F,F->S的次数,然后比较。

#include<stdio.h>
const int maxn=110;
char a[maxn];
int main(){
    int n;
    scanf("%d",&n);
    scanf("%s",a);
    int sf=0,fs=0;
    bool f;
    if(a[0]=='S') f=true;
    else f=false;

    for(int i=1;i<n;i++){
        if(a[i]=='S'){
            if(1&f==0) fs++;
            f=true;
        }
        else if(a[i]=='F'){
            if(1&f) sf++;
            f=false;
        }

    }
    if(sf>fs) printf("YES\n");
    else printf("NO\n");
    return 0;
}

B:题意大概是,给你一个零钱总数n,再给你m钟面值,然后列出m种面值,求出用m种面值的钱组成n的方案数目(每一种面值可以用任意次)。这题反过来,给你一个方案数目,自己给出总数n,和面值数m,以及m种面值。必然有规律,不然太麻烦了……,毕竟太多不确定的变量.
找规律,我们设置金额为n,方案数为a. 
n=1,  1=1, a=1    

n=2   2=2,2=1+1 a=2;
n=3   3=2+1=1+1+1  a=2;

n=4   4=2+2=1+1+2=1+1+1+1  a=3
n=5   5=2+2+1=1+1+2+1=1+1+1+1+1  a=3

...

我们只需要给出一个总金额n就行,所以  (a-1)*2=n

#include<stdio.h>

int main(){
    int n;
    scanf("%d",&n);
    if(n==1){
        printf("1 1\n1\n");
    }
    else{
        printf("%d 2\n",(n-1)*2);
        printf("1 2\n");
    }

    return 0;
}

C:
首先代码参考:http://blog.youkuaiyun.com/so_so_y/article/details/78152910  感谢大佬的分享
讲解一下思路,给你n个人,每个披萨有S块,一共有两种披萨A,B。然后每一行给出 s,a,b个人需要吃的块数以及 吃A获得的愉快感和吃B披萨获得的愉快感。
要求出用最少个数的披萨获得最多的愉快感。
首先,我们每次选取 ai,bi中最大的给第i个人吃,那么当前获得的愉快感为 si*max(ai,bi)  求和,并且每次存贮 max(ai,bi)-min(ai,bi), si 存进vector 数组中,用pair类型
同时计算吃a,b的总块数  re1  re2

全部计算之后,对re1=a%S,re2= b%S,也就是买A,B pizza不到一个的块数,如果re1+re2>S那么不用处理直接输出,因为不论怎么调整,都会多买一个。

如果 re1+re2<=S 那么我们就要处理一下。

a1为把多的re1 块 a全部换成b减少的值

a2为把多的re2 块 b 全部换成a减少的值

然后比较这两个值的大小,取较小的那个减去。即可。


#include <iostream>
#include <map>
#include <set>
#include <string>
#include<string.h>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
vector<pair<ll,ll>> vec1,vec2;
int main(){
    ll N,S;
    ll re1=0,re2=0,happy=0;
    scanf("%I64d%I64d",&N,&S);
    for(int i=0;i<N;i++){
        ll s,a,b;
        scanf("%I64d%I64d%I64d",&s,&a,&b);
        if(a>b){
            happy+=s*a;
            re1=(s+re1)%S;
            vec1.push_back(make_pair(a-b,s));
        }else{
            happy+=s*b;
            re2=(s+re2)%S;
            vec2.push_back(make_pair(b-a,s));
        }
    }
    if(re1+re2>S) printf("%I64d\n",happy);
    else{
        sort(vec1.begin(),vec1.end());
        sort(vec2.begin(),vec2.end());
        ll a1=0,a2=0;
        for(auto it=vec1.begin();it!=vec1.end();it++){
            a1+=min(it->second,re1)*it->first;
            re1-=min(it->second,re1);
        }
        for(auto it=vec2.begin();it!=vec2.end();it++){
            a2+=min(it->second,re2)*it->first;
            re2-=min(it->second,re2);
        }
        happy-=min(a1,a2);
        printf("%I64d\n",happy);
    }
	return 0;
}

E:智商题 

首先代码参考:http://www.cnblogs.com/onioncyc/p/7616959.html

中转站思想,建议模拟一遍代码,就好理解了,每次遇到一个值x,push(-x)两次,计算答案的时候用当前值加上队列中最大的负数,求和。

模拟一下代码的过程就理解了。

#include <iostream>
#include <map>
#include <set>
#include <string>
#include<string.h>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
int main(){
    int n;
    priority_queue<int> q;
    scanf("%d",&n);
    ll ans=0;
    for(int i=0;i<n;i++){
        int x;
        scanf("%d",&x);
        q.push(-x);
        q.push(-x);
        ans+=x+q.top();
        q.pop();
    }
    printf("%I64d\n",ans);
	return 0;
}

还需要努力啊,都不算很难,思维锻炼不够。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值