Educational Codeforces Round 108 (Rated for Div. 2)(A-D)

本文介绍了四道编程竞赛题目,涉及数组操作、最优化问题、学校编程水平分配及数组元素翻转策略。通过模拟和数学分析,给出了解题思路和代码实现,帮助读者理解竞赛中的解题技巧。

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

总结写在前头准没错,今天比赛前也有好好睡觉,可能起太晚了,一开始思维没活跃起来。
然后就是C的实现一言难尽,知道应该用vector开二维,但真不熟:(
外加没开ll加数组开小了:(
菜死了菜死了

A. Red and Blue Beans

题意: 你有红色球n个,蓝色球m个,假设你可以用无数个背包,每个背包里最少放一个红球和篮球,求背包中红色球和蓝色球相差最大个数的最小值。
思路:模拟着放,每个包都尽量按比例放n/m,然后判断差是否在K以内。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t,i,j,n;
    cin>>t;
    while(t--){
        int a,b,c;
        cin>>a>>b>>c;
        int ans=max(a,b)%min(a,b)==0?max(a,b)/min(a,b):max(a,b)/min(a,b)+1;
        if(ans-1<=c){scYES;}
        else scNO;
    }
 
    return 0;
}
 
 
 

B. The Cake Is a Lie

题意:起点是(1,1),有两种走法,一种是向右走,需要和横坐标一样大的花费,一种是向下走,需要和纵坐标一样大的花费,求最后的花费是否为k。

思路:其实一开始就觉得它的花费是定值,然后推花费的时候推错了,其实既然怎么走都是一样的花费,那我就走一条路求花费就行了,看别人的式子那么简单就一行就我模拟跑的

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t,i,j;
    cin>>t;
    while(t--){
            int n,m,k;
            cin>>n>>m>>k;
            int ans1=0;
            for(i=1;i<=n-1;i++){
                ans1+=1;
            }
            for(j=1;j<=m-1;j++){
                ans1+=i;
            }
            if(ans1==k){
                scYES;
            }
            else {
                scNO;
            }
    }
 
    return 0;
}
 
 
 

C. Berland Regional

题意:有n位同学,分别来自不同的学校,有不同的编程水平,每个学校可以派出n个队,求当每个队人数为k时,每个学校派出的队伍的编程水平总和。
思路:首先开个结构体先按照学校排序再按分数排,观察规律,不难发现如果学校的人数%每个队的人数=0时,即可全员出动,那么ans【k】就等于学校总人数的和,否则,每个队都会剩下一部分人无法组队,然后按照学校遍历,再按照人数遍历对答案有贡献的值即可(就是能派出的队伍),估摸着复杂度不会t,还可以用前缀和优化一下。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2*1e5+100000;
struct node {
    int u;
    int s;
}mo[maxn];
int u[maxn];
int ans[maxn];
int sum[maxn];
bool cmp(node a,node b){
    if(a.u==b.u){
        return a.s>b.s;
    }
    else {
        return a.u<b.u;
    }
}

signed main()
{
    int t,i,j,n,q;
    scanf("%lld",&t);
    while(t--){
            memset(ans,0,sizeof(ans));
           map<int ,int >m1;
           scanf("%lld",&n);
           for(i=0;i<n;i++){
                scanf("%lld",&u[i]);
                mo[i].u=u[i];
                m1[u[i]]++;
           }
           for(i=0;i<n;i++){
                scanf("%lld",&mo[i].s);
           }
           sort(mo,mo+n,cmp);
           int cnt=1;
           for(i=0;i<n;){
                int js=m1[cnt++];
                sum[0]=0;
                for(int d1=0;d1<js;d1++) {
                    sum[d1+1]=sum[d1]+mo[i+d1].s;
                }
                for(int k=1;k<=js;k++){
                    if(js%k==0) ans[k]+=sum[js];
                    else ans[k]+=sum[(js/k)*k];
                }
                 i+=js;
           }
            for( q=1;q<=n-1;q++){
                    printf("%lld ",ans[q]);
            }
              printf("%lld\n",ans[q]);
    }

    return 0;
}

D. Maximum Sum of Products

题意:给你两个数组a和b,它的总价值是相同位置相乘的和(a1×b1+a2×b2…这样),然后可以操作一次,翻转a数列的一个子区间,问翻转哪段子区间可以得到最大的价值。
思路:大佬说像区间dp,其实有点类似之前校赛做过的一道题,其实就是先选定一个点,然后扩大他们的左区间和右区间长度,那么他的翻转其实只有最外面的改变了 在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=5005;
signed  main()
{
    int n,i,j,k,a[maxn],b[maxn],sum=0;
    cin>>n;
    for(i=0;i<n;i++)       cin>>a[i];
    for(i=0;i<n;i++)       cin>>b[i];
    for(i=0;i<n;i++)       sum+=a[i]*b[i];
    int ans=sum;
    for(i=0;i<n;i++){
        int m1=sum;
        for(j=i-1,k=i+1;  (j<n&&j>=0)&&(k<n&&k>=0);  j--,k++){
            m1-=a[j]*b[j]+a[k]*b[k];
            m1+=a[j]*b[k]+a[k]*b[j];
            ans=max(ans,m1);
        }
        m1=sum;
         for( j = i, k = i + 1;  (j<n&&j>=0)&&(k<n&&k>=0);   j--, k++){
            m1 -= a[j] * b[j] + a[k] * b[k];
            m1 += a[j] * b[k] + a[k] * b[j];
            ans = max(ans, m1);
        }
    }
    cout<<ans<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值