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

来源:互联网 发布:德尔塔高达淘宝 编辑:程序博客网 时间:2024/05/23 02:03

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 nusing 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 0