Codeforces Round #412 (Div. 2)(Codeforces 807 ABCDE)

12 篇文章 0 订阅
5 篇文章 0 订阅

Codeforces Round #412 (Div. 2, base on VK Cup 2017 Round 3)

比赛时过了3题,rating暴涨90+。。一定是上次只做出一题拉低了rating。。这场感觉AB都是题面杀。。然后比赛时看了DE感觉都可做,赛后补了一下。
官方题解依旧是高质量,耐心读,即使是会的题,也绝对收获不少。样例代码也很棒。
官方题解传送门:%tourist

Codeforces 807A Is it rated?

题意

绝对的题面杀,反正我比赛时没读懂,只是按样例写了一发碰巧过了。大致意思是说,现在有一场CF比赛,按这场比赛打得由好到坏给你个表,第一列是这场比赛之前大家的分数(rating),第二列是这场比赛之后大家的分数(rating)。问你这场比赛是否计入排名。

思路

rating的含义:一场比赛下来,假设A打的比B好。比赛前,假设B的rating比A高,那么比赛后,A的rating不一定比B高,但是A的rating增量肯定比B高。
所以如果比赛前后有人Rating发生呢过了变化,那么肯定是rated比赛。如果比赛前后没人的rating的变化,且rating不是严格单调的。那肯定是unrated的比赛。否则就是maybe。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=10000+7;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;

int ra[1005];

int main()
{
    _;
    int n;
    while(cin>>n)
    {
        bool flag=false;
        for(int i=0;i<n;i++)
        {
            cin>>ra[i]>>ra1[i];
            if(ra[i]!=ra1[i])
            {
                flag=true;
            }

        }
        bool flag1=false;
        if(flag==false)
        {
            for(int i=1;i<n;i++)
            {
                if(ra[i-1]<ra[i])
                {
                    flag1=true;
                    break;
                }
            }
        }
        if(flag==true)
        {
            cout<<"rated"<<endl;
        }
        else
        {
            if(flag1==false)
            {
                cout<<"maybe"<<endl;
            }
            else
            {
                cout<<"unrated"<<endl;
            }
        }
    }

    return 0;
}

Codeforces 807B T-Shirt Hunt

题意

题面杀。。给你三个数abc,现在我的分数是b,我是rank1,我预计至少分数不能低于c分才是rank1。我的id是a,那么我要hack多少次才能拿到T桖。那到T桖的人的id根第一名的分数有关。具体公式看原文吧。

思路

读懂题就很简单了,暴力枚举就行。

代码

#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=10000+7;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;

vector<int> res;

int main()
{
    _;
    LL n;
    while(cin>>n)
    {
        LL now, low;
        cin>>now>>low;
        LL pre=now;
        bool flag=false;
        while(now>=low)
        {
            LL ti=(now/50)%475;
            for(int i=0;i<25;i++)
            {
                ti=(ti*96+42)%475;
                if(n==ti+26)
                {
                    flag=true;
                    break;
                }
            }

            if(flag) break;
            now-=50;
        }
        if(!flag)
        {
            now=pre;
            while(1)
            {
                LL ti=(now/50)%475;
                for(int i=0;i<25;i++)
                {
                    ti=(ti*96+42)%475;
                    if(n==ti+26)
                    {
                        flag=true;
                        break;
                    }
                }

                if(flag) break;
                now+=50;
            }
        }
        LL tt=now-pre;
        if(tt>0)
        {
            tt=(tt+50)/100;
        }
        else
        {
            tt=0;
        }
        cout<<tt<<endl;
    }
    return 0;
}

Codeforces 807C Success Rate

题意

我现在的ac题目是x,总提交是y。我想达到的正确率是p/q,问至少需要提交多少题才能达到我想要的正确率。

思路

因为pq互质,所以要想达到正确率,可以将pq都扩大n倍,得到 npnq 。正确的题数是np,错误的题是nq-np,分别大于x与y-x即可。另外还有logn的二分,因为不等式是单调的,所以可以二分n。官方题解写的很详细。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=10000+7;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;

vector<int> res;

int main()
{
    _;
    LL n;cin>>n;
    while(n--)
    {
        LL x, y, p, q;
        cin>>x>>y>>p>>q;


        if(q==p&&x<y)
            cout<<-1<<endl;
        else if(x>0&&p==0)
            cout<<-1<<endl;

        else
        {


            LL a=y-x;
            LL b=q-p;
            LL c=ceil(1.0*a/b);
            c=max(c, (LL)ceil(1.0*x/p));


            cout<<c*q-y<<endl;
        }
    }
    return 0;
}

Codeforces 807D Dynamic Problem Scoring

题意

CF过题的分数计算是动态的,每道题总分与过了这题人数与参与比赛(有过submit)的人数之比有关。另外你的得分还与你ac的时间有关。
然后现在假设所有参与者的过题时间(某题没过时间就是-1),给你了,再也不会有变化。有个作弊者(0号),他注册了很多小号,他可以让他的小号提交正确/错误的sunmit来改变某题的分数。注意如果他没过某题,他的小号不能提交正确的submit。问他要想分数比1号人高,他至少需要多少个小号。

思路

乍一看很乱,看了题解自习想想,情况很少。
1. 首先,一道题X,如果他没过,对手过了,那么他想最小化总分,他不应该提交这题。
2. 如果他与对手都没过或者过的时间一样,那么他也不应该管,因为没用。
3. 如果他过得时间比对手早,那么他想最大化总分,他应该提交错误的submit。
4. 如果他过得比对手晚,他应该提交正确的submit。

现在枚举小号数。注意枚举小号数时,我们是假设这些小号都存在了,所以不需要考虑错误的提交了。只需要找出需要进行正确提交的题,并提交。在计算总分,看他是否超过了对手。从小枚举到大,保证了我们不用考虑提交错误答案。

所以是否存在某种情况,他的小号只应该提交错误的submit,不能提交正确的submit,而按照上面的分析,又没有可以让他提交错误submit的题,这样我们的程序就gg了?

我开始也困在这了。仔细想想,按照上面的分析,这种情况只能发生在他所有题都比对手晚。这样他是永远不可能超过对手的。而我们的代码不会让他的小号提交题,自然他也永远不可能超过对手。

枚举小号数到什么时候停止呢?n最大120,只要到31*n,保证所有题都到了最大份即可。

看代码吧,或者写一遍。我就是写着写着就明白了。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
#define N n
using namespace std;
const int MAXN=10000+7;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;

int t1[6];
int t2[6];
int speo[6];
int judge(int sov, int sub)
{
    if(32*sov<=sub) return 3000;
    else if(16*sov<=sub) return 2500;
    else if(8*sov<=sub) return 2000;
    else if(4*sov<=sub) return 1500;
    else if(2*sov<=sub) return 1000;
    else return 500;
}
int main()
{
    _;
    int n;
    while(cin>>n)
    {
        M(t1, 0);M(t2, 0);M(speo, 0);
        for(int i=0;i<n;i++)
        {
            if(i==0) cin>>t1[1]>>t1[2]>>t1[3]>>t1[4]>>t1[5];
            else if(i==1) cin>>t2[1]>>t2[2]>>t2[3]>>t2[4]>>t2[5];
            else
            {
                int q;
                for(int j=0;j<5;j++)
                {
                    cin>>q;
                    if(q!=-1) speo[j+1]++;
                }
            }
        }
        for(int i=1;i<=5;i++)
        {
            if(t1[i]!=-1) speo[i]++;
            else t1[i]=250;
            if(t2[i]!=-1) speo[i]++;
            else t2[i]=250;
        }
        int res;
        for(res=0;res<3840;res++)
        {
            int mark1=0, mark2=0;
            int sump=n+res;
            for(int j=1;j<=5;j++)
            {
                int tmpsepo=0;
                if(t1[j]==250)
                {

                }
                else if(t1[j]<t2[j])
                {

                }
                else if(t1[j]>=t2[j])
                {
                    tmpsepo=res;
                }

                mark1+=(judge(speo[j]+tmpsepo, sump)*(250-t1[j])/250);
                mark2+=(judge(speo[j]+tmpsepo, sump)*(250-t2[j])/250);
            }
            if(mark1>mark2) break;
        }
        cout<<(res==3840 ? -1 : res)<<endl;
    }

    return 0;
}

Codeforces 807E Prairie Partition

题意

思路

读入一个数,判断他是整数次幂还是有余数,分别存到power和between里。注意到序列最大数量一定是1的个数,且答案是连续的,所以只需要求出最小的序列个数,二分左端点。二分的时候判断一下 即可。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
#define N n
#define max3(a,b,c) std::max(a,std::max(b,c))

using namespace std;
const int MAXN=10000+7;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;

int power[70+10];
int between[70+10];
int sy[70+10];
int xl[70+10];

int main()
{
    _;
    int n;
    while(cin>>n)
    {
        M(power, 0);M(between, 0);M(sy, 0);M(xl, 0);
        //int mp=0;
        for(int i=0;i<N;i++)
        {
            LL t;cin>>t;
            int p=0;bool fl=false;
            while(t>1)
            {
                if(t&1) fl=true;
                t=t>>1;p++;
            }
            if(fl) between[p]++;
            else power[p]++;
            //if(!fl) mp=max(mp, p);
        }
        int l=1, r=power[0]+1;
        while(l<r)
        {
            int mid=(l+r)/2;
            int now=mid;
            for(int i=0;i<=70;i++)
            {
                sy[i]=power[i]-now;
                int tnow=now;
                if(power[i+1]<tnow)
                {
                    tnow=power[i+1];
                }
                xl[i]=now-tnow;
                now=tnow;
            }
            bool fl=false;
            int tt=0;
            for(int i=70;i>=0;i--)
            {
                tt+=xl[i];
                tt-=between[i];
                tt-=sy[i+1];
                if(tt<0) { fl=true;break; }
            }
            tt-=sy[0];
            if(tt<0) { fl=true; }
            if(fl)
            {
                l=mid+1;
            }
            else
            {
                r=mid;
            }
        }
        if(l<=power[0])
        {
            for(int i=l;i<=power[0];i++)
            {
                cout<<i<<' ';
            }
            cout<<endl;
        }
        else cout<<-1<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值