Educational Codeforces Round 103 (Rated for Div. 2)

58 篇文章 0 订阅
35 篇文章 1 订阅

还没系统测试。仅供参考。

A. K-divisible Sum

题意:给定n,k。让找一个n个元素的数组,数组和可以整除k。并且数组中元素的最大值 最小。

思路:如果n == k。那显然是1。 如果n > k,分两种情况。n%k == 0。那么全是1,和就是k的倍数了。否则,必须要有一些2。去凑成余数。所以最大值是2。 接着考虑 n < k,至少要和加起来要等于一个k。(k+n-1)/n 就是答案。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#include <unordered_map>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e6+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n>>k;
        if(n >= k){
            if(n%k == 0)cout<<1<<endl;
            else cout<<2<<endl;
        }else{
            cout<<(n+k-1)/n<<endl;
        }
    }
    return 0;
}

B. Inflation

题意:给一个数组,和一个k。要让这个数组保持这个性质。可以给一些数增加一些值。问最小的增加量。

如图,左边分子是a[i]分母是前i-1项和。右边分子是k,分母是100;保持这个性质就行了 。

在这里插入图片描述

思路:很容易发现,下面是前缀和嘛。 要让分数变小,肯定是前缀和越大越好。那肯定把所有的增量都增加到a[0]上去。不就行了。然后就是计算这个增量了。对于每一项。分子其实都是独立的。那么可以直接求出,保持这个比例。需要的前缀和是多少!然后与真实的前缀和的差值。就是当前这个点保持性质需要的增量。所有项要保持性质需要的的最大增量就是答案了。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#include <unordered_map>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e6+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n>>k;
        int tot = 0;
        for(int i = 0 ; i < n ; i ++){
            cin>>a[i];
            tot += a[i];
        }
        for(int i = 0 ;i < n ; i ++){
 
        }
        int last = a[n-1];
        int sum = 0;
        int res = 0;
        int maxx = 0;
        tot -= a[n-1];
        for(int i = n-2 ; i >= 0 ; i --){
            sum = (100*last+k-1)/k;
            last = a[i];
            //cout<<sum<<" "<<tot<<endl;
            int tmp  = max(0LL,sum-tot);
            maxx = max(maxx,tmp);
            tot -= a[i];
        }
        cout<<maxx<<endl;
    }
 
    return 0;
}

C. Longest Simple Cycle

题意:n个柱子。每个柱子从上到下c[i]个点。然后相邻两个柱子之间都有两条边。分别是从c[i]的头上和脚上引出来的两条边。分别连接c[i-1]的a和b点。 有点绕。最终这样形成一个图型的结构,求最大的环大小。

思路:贪心。从最后一根柱子往前访问过去。最后一根柱子就有 c[i]-1条边了。然后往前走。分情况讨论。

在这里插入图片描述

1. 两个落脚点在同一个位置。那这个环就已经结束了。没有选择的余地。从新开始另一个环。从这个点 向上下走就行了。
2. 上面的落脚点在上面。下面的在下面。那么就接着上面往上走,下面往下走。可以把这个环一直延续下去。直到走到1那种情况 或者走到第一根柱子结束。
3. 显然,与2相反。这个也很简单。交换一下 上下就好了。swap(up,down)。

然后在求解的过程中。用now记录当前已经在环上的边的数量。maxx记录全局最大值。 不过遍历的过程要注意now的贪心法则。碰到第一种情况。 不用贪心。没得选。 但是对于2,3来说。有可能 now的值还没有 中间那部分没走的多! 那以中间某个点为起点,另起一个环,岂不是更大了嘛。这时候就得更新now的值。 要注意第一根柱子的特殊性。除了up-down之内的点。 是不可能在环上的。那些点全当不存在就是了。特判一下就行。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#include <unordered_map>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e6+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N],c[N];
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n;
        for(int i = 0 ; i < n ; i ++) cin>>c[i];
        for(int i = 0 ; i < n ; i ++) cin>>a[i];
        for(int i = 0 ; i < n ; i ++) cin>>b[i];
        int maxx = 0;
        int last = 0;
        int now = c[n-1]-1;
        int up = 0;
        int down = 0;
        for(int i = n-1 ; i >= 1 ; i --){
            up = a[i];
            down = b[i];
            now += 2;
            if(up == down){
                maxx = max(maxx,now);
                if( i >= 2){
                    now = c[i-1]-1;
                }else now = 0;
            }else if(up > down){
                swap(up,down);
                maxx = max(maxx,now+abs(up-down));
                if( i >= 2){
                    now += up-1;
                    now += c[i-1]-down;
                    now = max(now,c[i-1]-1);
                }
            }else{
                maxx = max(maxx,now+abs(up-down));
                if( i >= 2){
                    now += up-1;
                    now += c[i-1]-down;
                    now = max(now,c[i-1]-1);
                }
            }
        }
        maxx = max(maxx,now);
        cout<<maxx<<endl;
    }
    return 0;
}

D. Journey

题意:有n+1个城市。n条有向边,连接 i -> i+1。然后现在商人以一个点为起点开始遍历。每移动一次,所有的边就会调转方向。问以所有i为起点。能访问到的城市的数量。

思路:分类讨论。前后缀和。因为每走一次就会方向。所以不管走到哪都能沿路返回到起点。假设现在在x点。然后往左走。走到不能走了。再回来。回到起点。就像什么也没发生一样。但是已经遍历完了左边能遍历的点。接着对右边进行遍历。所以求解肯定是分左右分别进行讨论。然后考虑到底能走哪些。 对于左边。 如果是 LRLRLX,就可以一直走。只要LR交替。就能一直走。不过前提是起点的左边必须是L。同理 右边也是RLRL交替就可以走。 起点右边必须是R。最后再特殊考虑一下左右两端点。LR交替出现的次数,用前缀和维护就好了。前后各维护一次。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#include <unordered_map>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e6+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N],c[N];
int sum1[N];
int sum2[N];
int res[N];
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n;
        string s;
        cin>>s;
        sum1[0] = 1;
        for(int i = 1 ; i < n ; i ++){
            if(s[i] == s[i-1]) sum1[i] = 1;
            else sum1[i] = sum1[i-1]+1;
        }
        sum2[n-1] = 1;
        for(int i = n-2; i >= 0 ; i --){
            if(s[i] == s[i+1]) sum2[i] = 1;
            else sum2[i] = sum2[i+1]+1;
        }
        for(int i = 1; i <= n-1 ; i ++){
            res[i] = 1;
            //cout<<s[i-1]<<" "<<i<<" "<<s[i]<<endl;
            //cout<<sum1[i-1]<<" "<<sum2[i]<<endl;
            if(s[i-1] == 'L') res[i] += sum1[i-1];
            if(s[i] == 'R') res[i] += sum2[i];
        }
        if(s[0] == 'R'){
            res[0] = sum2[0]+1;
        }else{
            res[0] = 1;
        }
        if(s[n-1] == 'L'){
            res[n] = sum1[n-1]+1;
        }else{
            res[n] = 1;
        }
        for(int i = 0 ; i <= n ; i ++)
            cout<<res[i]<<" ";
        cout<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 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、付费专栏及课程。

余额充值