Educational Codeforces Round 77 题解报告

A、Heating

【题意、思路、解题过程及其感想】

题意大体是,给定两个数c,和sum,表示划分几段和总面积,让你求出覆盖全部面积的最小价值,价值 = 每一段面积的平方之和。
思路首先从划分段来考虑,例如 c=4,sum=6,将6分成4段,要使最小价值最小,那么就要让每一段之间的差值最小,即分成 1 1 2 2。其实明白题意后就可以更容易想出思路,要使价值最小,那么首先看sum能否将c整除,如果能整除的话正好,不能整除的话就将sum%c分配到每一个分段即可。
这道题看了半天才看明白题意。
数论很重要。

【代码】
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
int main()
{
    int t;
    cin >> t; 
    while(t--)
    {
        ll c,sum,x,y;
        cin >> c >> sum;
        x = sum/c;
        y = sum%c;
        ll ans = (c-y)*x*x + y*(x+1)*(x+1);
        cout << ans <<endl;
    }
}

B、Obtain Two Zeroes

【题意、思路、解题过程及其感想】

题意大体是,有两个数a,b,每次可以进行一种操作:(a-x,b-2x)或者(a-2x,b-x),问能否将a,b置为0。
其实这道题目判断上有很多种方法,关键一点就是验证能否成立。
要想a,b都置为0的话,他们的和首先要是3的倍数,因为无论是(a-x+b-2x)=0还是(a-2x+b-x)=0还是(a-2x-y+b-2y-x)=0,最后a+b肯定是3的倍数,之后就是验证能否成立了。
a = 2x+y; b = x+2y;
a - 2x - y + b - 2y - x = 0 --> a+b = 3x + 3y --> (a+b)/3 = x+y
推出这几条公式就可以了,之后就验证最初的式子是否成立就可以了。
刚开始直接判断a+b内否被3整除结果wa了,最后发现验证方法不同也可以。

【代码】
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        ll a,b;
        cin >> a >> b;
        ll sum = (a+b)%3;
        if(sum)
        {
            cout << "NO" <<endl;
            continue;
        }
        ll tt=(a+b)/3;
        ll x = a-tt,y = b-tt;
        if(x<0||y<0)
            cout << "NO" <<endl;
        else
            cout << "YES" <<endl;
    }
}

C、Infinite Fence

【题意、思路、解题过程及其感想】

题意是给 1 0 100 10^{100} 10100个色块涂色。给出r和b的值,r的倍数涂红色,b的倍数涂蓝色,r和b的倍数自己选择颜色,讲涂色的色块按编号从小到大排号,要求不能有连续k个色块是同一个颜色。
这个题是用的扩展欧几里得算法。
我们先假设r是小的,b是大的。那么最长连续区间肯定是r的倍数染的色。b的染色情况为b,2b,3b…kb。r可以出现的位置肯定在两个b的倍数之间,那么r可以出现的区间长度肯定是b−1。我们考虑最坏的情况那r在一个区间出现大的位置肯定要尽可能的早设这个位置为t。那么满足式子 k 1 k_{1} k1b+t= k 2 k_{2} k2r。由 exgcd可得 ax+by=c当且仅当 gcd(a,b)∣c有解。c 最小为gcd(a,b)。即t最小为 gcd(r,b)。则最多连续的木板数为 ( b − 1 ) − g c d ( r , b ) r \frac{(b−1)−gcd(r,b)}{r} r(b1)gcd(r,b)。把这个数和k比较就能得到答案。
这道题没ac,看题一直没看出来怎么解,后来找题解才发现用的扩展欧几里得算法。

【代码】
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
int gcd(int a,int b)
{
    return b==0 ?a:gcd(b,a%b);
}
int main()
{
    int t,r,b,k;
    cin >> t;
    while(t--)
    {
        cin >> r >> b >> k;
        int g=gcd(r,b);
        if(r>b) swap(r,b);
        cout << ((b-1-g)/r+1>=k?"REBEL":"OBEY") <<endl;
    }
}

D、A Game with Traps

【题意、思路、解题过程及其感想】

给你m个小兵的敏捷值ai,要求你们从0走到n+1。存在k个陷阱,从li开始,你走到ri的时候可以撤销它,如果小兵的敏捷值低于di,他就会被杀死。你可以选择自己一个人或者和小兵一起向前或向后走一个单位,每次耗时1秒。给你t秒,问你最多可以带多少小兵到达n+1处。
我们由题可以得到,我和小兵必须走的路径长度是n+1。所以求能拆掉最大的陷阱,以便带最多的小兵数量。我们可以把小兵排序,二分人数。把大于小兵的位置标记,需要走的路程即为标记的长度len*2+n+1。
这道题做的时候没有看,C和E看了很久没看出来怎么解,这道题也没得看,确实很难理解

E、Tournament

【题意、思路、解题过程及其感想】

给你n个人(n=2^k)进行拳击比赛,每次将m人分成m/2对比赛,对于下标i>j,就是i获胜,但是你可以贿赂ai块让i输。你想让你的朋友获得最终胜利,你的朋友的ai值为-1,问你最少要花多少钱。
记朋友位置为id,我们从后面推一下,如果id!=n,那要贿赂第n个选手;如果id<n/2,那要贿赂[n/2~n)中最小的一个……可以用优先队列存贿赂的钱,按从小到大排,每次取出队头,加起来即为最小值。也是看了很久没想到解决方案……确实很烦。。

【代码】
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
int a[1000000];
priority_queue<ll,vector<ll>,greater<ll> > que;
int main()
{
 ll n,id;
 ll res=0;
 cin>>n;
 for(int i=1;i<=n;i++)
 {
  cin>>a[i];
  if(a[i]==-1)
   id=i;
 }
 ll k=n;
 while(k>id)
 {
  for(int i=k;i<2*k&&i<=n;i++)
   que.push(a[i]);
  res+=que.top();
  que.pop();
  k/=2;
 }
 cout<<res<<endl;
 return 0;
}
F

f题确实没仔细看,f题是关于树的,然后专注其他的题目去了。。。

感觉做的有点差,因为确实只解出了最简单的两道题目,然后今天下午和晚上还有课和宣讲要听,剩下的几道看题解也看的半半卡卡的,先这样吧,明天下午补一下算法和题解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅梦曾倾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值