Educational Codeforces Round 120 (Rated for Div. 2)简训

导语

日常

涉及的知识点

思维,二分,贪心

链接: Educational Codeforces Round 120 (Rated for Div. 2)

题目

A Construct a Rectangle

题目大意:给出三个的木条(长度为整数),现在需要挑选一根木条进行切割,保证得到的四根木条能够组成矩形,对于给定的木条判断是否能通过一次切割组成矩形

思路:判断是否存在一个能分成其余两条之和,或者判断是否有两条相等且另一条能一分为二

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >>t;
    while(t--) {
        int a[4];
        for(int i=1; i<=3; i++)cin >>a[i];
        sort(a+1,a+4);//排序便于判断能否加起来等于
        if(a[1]+a[2]==a[3]||(a[2]==a[3]&&a[1]%2==0)||(a[1]==a[2]&&a[3]%2==0))
            cout <<"yes\n";
        else
            cout <<"no\n";
    }
    return 0;
}

B Berland Music

题目大意:略

思路:分别收集喜爱与不喜爱的原价值,然后排序按照题设条件重新赋值即可

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+5;
int t,n,a[maxn],b[maxn];
bool vis[maxn];
vector<int>zero,one;
signed main() {
//    ios::sync_with_stdio(false);
//    cin.tie(0);
    cin >>t;
    while(t--) {
        cin >>n;
        for(int i=1; i<=n; i++)cin >>a[i];
        one.clear();
        zero.clear();
        for(int i=1; i<=n; i++) {
            int x;
            scanf("%1lld",&x);
            if(x)one.push_back(a[i]);//分别统计喜爱与不喜爱的价值
            else zero.push_back(a[i]);
        }
        int ans=n;
        sort(one.begin(),one.end());//重新排序
        int len=one.size();
        for(int i=len-1; i>=0; i--)//重新分配价值
            b[one[i]]=ans--;
        sort(zero.begin(),zero.end());
        len=zero.size();
        for(int i=len-1; i>=0; i--)
            b[zero[i]]=ans--;
        for(int i=1; i<=n; i++)
            cout <<b[a[i]]<<" ";
        cout <<endl;
    }
    return 0;
}

C Set or Decrease

题目大意:给出一共整数序列 a a a和一个整数 k k k,每一步可以选择一个下标 i i i,然后使 a i − 1 a_i-1 ai1,或者选择两个下标 i , j i,j i,j使得 a i = a j a_i=a_j ai=aj,求出能使得 ∑ i = 1 n a i ≤ k \sum_{i=1}^n a_i\le k i=1naik的最小操作次数

思路:贪心的来想,肯定是对最小值-1,多次-1之后让大值赋值为最小值即可,暴力尝试对几个大值赋值,然后二分获得给最小值-1的次数

代码

#include <bits/stdc++.h>
#define int long long
const int inf=0x3f3f3f3f;
using namespace std;
const int maxn=2e5+5;
int t,a[maxn],k,n,pre[maxn];
bool Judge(int len,int x) {
    int sum=pre[n-len]-a[1]+x*(len+1);
    return sum<=k;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>t;
    while(t--) {
        cin >>n>>k;
        for(int i=1; i<=n; i++)cin >>a[i];//记录数据
        sort(a+1,a+1+n);//排序
        for(int i=1; i<=n; i++)pre[i]=pre[i-1]+a[i];
        //前缀和
        int res=2*inf,ans=0;
        for(int i=0; i<=n-1; i++) {//i为最大的i个数被赋值为a[1]
            int l=-inf,r=inf;
            while(l<r) {
                int mid=l+r+1>>1;
                if(Judge(i,mid))//mid为对a[1]进行几次-1
                    l=mid;
                else
                    r=mid-1;
            }
            res=min(res,max(0ll,a[1]-l)+i);
            //a[1]-l为对a[1]减了几次,为负值代表不用减就能满足
        }
        cout <<res<<endl;
    }
    return 0;
}

D Shuffle

题目大意:给出一个01串,定义一个操作:选择串中的一个严格有k个1的子串然后重新排列再放回去,现在只能进行一次这个操作,求出最后能构造出多少种字符串

思路:由于长串的排列组合的结果包括短串的结果(例如1100和110,前者必然包括了后者的排列结果),所以枚举每种尽可能长的包括k个1的子串,并且去重,那么,如何去重呢?
如图,两个相邻的极长子串(假设k=2)在计算排列组合时,圈起来的地方是重复的,分别计算两个极长子串的排列数然后减去重复数即可,但是重复的部分只能插k-1个1,因为两个子串有一个1是公用的
在这里插入图片描述

代码

#include <bits/stdc++.h>
#define int long long
const int inf=0x3f3f3f3f;
using namespace std;
const int maxn=5e3+5;
const int mod=998244353;
int c[maxn][maxn],t;
vector<int>pos;
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    for(int i=0; i<maxn; i++) {//预处理组合数的值
        c[i][0]=1;
        for(int j=1; j<=i; j++)
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
    }
    int n,k,res=0;
    cin >>n>>k;
    string s;
    cin >>s;
    pos.push_back(0);//塞一个0方便下标从1开始
    for(int i=0; i<n; i++)
        if(s[i]=='1')pos.push_back(i+1);//把1的下标塞进去,默认从1开始
    pos.push_back(n+1);//多塞一个作为结尾,方便统计
    int len=pos.size();
    for(int i=k; i<len-1; i++) {//以长度为k开始取
        res=(res+c[pos[i+1]-pos[i-k]-1][k])%mod;
        //pos[i+1]-pos[i-k]-1为极长串的长度
        if(i>k)res=(res-c[pos[i]-pos[i-k]-1][k-1]+mod)%mod;
        //去重,由于有一个1是公用的,所以是k-1
    }
    if(k==0||len-2<k)cout <<1<<endl;//特判
    else cout <<res<<endl;
    return 0;
}

参考文献

  1. C. Set or Decrease—二分+贪心
  2. Educational Codeforces Round 120 (Rated for Div. 2) D. Shuffle(组合数学+巧妙去重)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值