当前位置: 首页 > news >正文

Codeforces Round #828 (Div. 3)-赛后总结

Dashboard - Codeforces Round #828 (Div. 3) - Codeforces

打完比赛的晚上美滋滋的看着解出来的六道题,心想着能够加上一百多分。一觉醒来眼睁睁看着E1E2被hack掉,排名从前一百掉到快两千,落差感是很大的。但不管怎么说也算是有些收获。

总结就是

1. CF的原始数据仅仅是全部数据的冰山一角,赛时过不代表一定过。

2. 不要去想算法,不要去想算法,否则一定会被牵制住思维!

Problem - A - Codeforces

给定n个数字,n位字符串,原始操作是给一种数字涂上相同的字符。

判断是否数字相同时对应的字母也是相同。

#include<bits/stdc++.h>
using namespace std;

typedef long long int  ll;
int a[100];
string s;
int main()
{
	int t;
	cin>>t;

	while(t--)
    {
        int n;
        cin>>n;

        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }

        cin>>s;

        s=" "+s;

        int flag=0;

        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(a[i]==a[j])
                {
                    if(s[i]!=s[j])
                    {
                        flag=1;
                    }
                }
            }
        }

        if(flag)
        {
            cout<<"NO"<<endl;
        }
        else
        {
            cout<<"YES"<<endl;

        }
    }
	return 0;
}

Problem - B - Codeforces

B. Even-Odd Increments

给定0 1操作,0代表给全部偶数加上 y  1代表给全部奇数加上y  

是一道模拟题,只需要维护奇数个数,偶数个数,奇数和,偶数和即可,y的奇偶使得数列中的奇数偶数性质得到不断变换或者不变。

#include<bits/stdc++.h>
using namespace std;

typedef long long int  ll;

int a[100000+10];
int main()
{


    int t;
    cin>>t;

    while(t--)
    {
        int n,q;
        cin>>n>>q;
        ll cntji=0,cntou=0,sumji=0,sumou=0;

        for(int i=1; i<=n; i++)
        {
            cin>>a[i];

            if(a[i]&1)
            {
                cntji++;
                sumji+=a[i];
            }
            else
            {
                cntou++;
                sumou+=a[i];
            }
        }

        while(q--)
        {
            ll x,y;
            cin>>x>>y;

            if(x==0)
            {

                if(y&1)
                {
                    sumou+=cntou*y;
                    sumji+=sumou;
                    sumou=0;
                    cntji+=cntou;
                    cntou=0;

                }
                else
                {
                    sumou+=cntou*y;
                }

            }
            else
            {

                if(y&1)
                {
                    sumji+=cntji*y;
                    sumou+=sumji;
                    sumji=0;
                    cntou+=cntji;
                    cntji=0;
                }
                else
                {
                    sumji+=cntji*y;

                }
            }

            cout<<sumji+sumou<<endl;

        }

    }
    return 0;
}

Problem - C - Codeforces

C. Traffic Light

给定红绿灯与灯的字符串序列(可以循环),找到给定颜色最远的绿灯。首先绿灯一定是0

红黄的话只需要将字符串扩大一倍,开启后缀DP,倒叙遍历求出距离位置i的最近绿灯即可。然后我们统计最大值。

不少人赛后被HACK,是因为赛时数据极水,暴力n2都能过,然而赛时数据仅仅是冰山一角

#include<bits/stdc++.h>
using namespace std;

typedef long long int  ll;

int dp[200000*2+2];
int main()
{


int t;
cin>>t;
while(t--)
{
    int n;
    char r;
    cin>>n>>r;

    string s;
    cin>>s;

    if(r=='g')
    {
        cout<<0<<endl;
    }

    else
    {
        s=s+s;

        dp[2*n]=1e9;

        for(int i=2*n-1;i>=0;i--)
        {
            if(s[i]=='g')
            {
                dp[i]=i;
            }
            else
            {
                dp[i]=dp[i+1];

            }
        }

        int ans=0;
        for(int i=0;i<n;i++)
        {
            if(s[i]==r)
            {
                ans=max(ans,dp[i]-i);
            }
        }

        cout<<ans<<'\n';

    }
}


	return 0;
}

Problem - D - Codeforces

原序列乘积能被2^n整除的数学表示就是原序列包含了超过n个2,如果原序列已经包含了超过n个2,那么一定可以且耗费是0,。接下来就是需要我们人工添加下标的操作了,既然要求次数最少,干脆on遍历全部下标,求出来其中含有2的个数。排序贪心取即可

#include<bits/stdc++.h>
using namespace std;

typedef long long int  ll;

ll a[100000*2+10];

int tempfuck[100000*2+10];


bool cmp(int a,int b)
{
    return a>b;

}
int main()
{

    int t;
    cin>>t;

    while(t--)
    {
        int n;
        cin>>n;

        int cnt=0;

        for(int i=1; i<=n; i++)
        {
            cin>>a[i];

            ll tempx=a[i];

            while(tempx&&tempx%2==0)
            {
                cnt++;
                tempx/=2;

            }
        }

        if(cnt>=n)
        {
            cout<<0<<endl;
        }
        else
        {
            int temp=0,fuck=0,ans=0;
            for(int i=n; i>=1; i--)
            {


                tempfuck[i]=0;
                temp=0;

                if(i%2)
                    continue;



                int tempx=i;

                while(tempx&&tempx%2==0)
                {
                    temp++;
                    tempx/=2;

                }

                tempfuck[i]=temp;

            }

            sort(tempfuck+1,tempfuck+1+n,cmp);

            temp=0;

            for(int i=1; i<=n; i++)
            {
                temp+=tempfuck[i];

                if(temp+cnt>=n)
                {
                    ans=i;
                    break;
                }
            }
            if(temp+cnt>=n)
            {
                cout<<ans<<endl;
            }
            else
            {
                cout<<-1<<endl;

            }
        }

    }


    return 0;
}

Problem - E1 - Codeforces

对a*b进行因数拆分,我们求出来一个  i  一个  a*b/i 。只需要包含这两个部分,我们的x,y就一定能够满足对a*b的整除。而我们根据   a  b可以直接定位出来第一个大于a且整除i的数,作为x.另一个配对的因数作为y即可。时间复杂度也就 sqrt(a*b),是一定不会被卡掉的。

赛时看到4秒还以为可以胡搞,于是就敲了一个枚举倍数的暴力。。。数据很水跑了31ms...赛后被卡到4s+...

# include<iostream>
using namespace std;
typedef long long int  ll;

ll a,b,c,d,ans1,ans2;


bool check(ll x, ll y)
{
    ll tempans1=(a+x)/x*x;


    ll tempans2=(b+y)/y*y;

    if(a<tempans1&&tempans1<=c&&tempans2>b&&tempans2<=d)
        {
            ans1=tempans1;
            ans2=tempans2;

            return 1;

        }
    return 0;
}
int main ()
{
    int t;
    cin>>t;

    while(t--)
    {
        cin>>a>>b>>c>>d;

        ans1=-1,ans2=-1;

        int flag=0;
        for(ll i=1;i*i<=a*b;i++)
        {
            if(a*b%i==0)
            {


                if(check(i,a*b/i))
                {

                    flag=1;
                    break;

                }

                if(check(a*b/i,i))
                {

                    flag=1;
                   break;
                }

            }
        }

        if(flag)
        {
            if(ans1>a&&ans1<=c&&ans2>b&&ans2<=d)
            {
                cout<<ans1<<" "<<ans2<<endl;
            }
            else
            {
                cout<<ans2<<" "<<ans1<<endl;
            }
        }
        else
        {
            cout<<-1<<" "<<-1<<endl;
        }
    }
    return 0;
}

Problem - E2 - Codeforces

E1是对ab进行了因数分解,如果E2再进行分解可以发现明显的超时。这时完全可以对a,b单独进行分解,然后我们不难发现因数其实是很少的,暴力枚举两个因数的组合当做x的基底,另外一个只需要除以这个基底。这个暴力枚举的过程其实就等价于我们对a*b拆分因数的过程。时间复杂度很低,不会被卡。

赛时我想到了一个类似的,那就是枚举a,b的全部质因子,枚举每种搭配,枚举倍数,然而这种方法一旦倍数很多时是很容易被卡掉的。

# include<iostream>
# include<vector>
using namespace std;
typedef long long int  ll;

vector<ll>x,y;

int main ()
{

    int t;
    cin>>t;

    while(t--)
    {
        ll a,b,c,d;
        cin>>a>>b>>c>>d;

        x.clear();
        y.clear();
        ll tempx=a,tempy=b;

        for(ll i=1;i*i<=a;i++)
        {
            if(a%i==0)
            {
                x.push_back(i);
                x.push_back(a/i);
            }
        }

        for(ll i=1;i*i<=b;i++)
        {
            if(b%i==0)
            {
                y.push_back(i);
                y.push_back(b/i);
            }
        }
        ll ans1=-1,ans2=-1;

        int flag=0;
        for(auto it1:x)
        {
            for(auto it2:y)
            {
                ll now=it1*it2;

                ll temp=a*b/now;

                tempx=(a+now)/now*now;
                tempy=(b+temp)/temp*temp;

                if(tempx>a&&tempx<=c&&tempy>b&&tempy<=d)
                {
                    ans1=tempx;
                    ans2=tempy;



                    flag=1;
                    break;
                }

                tempy=(b+now)/now*now;

                tempx=(a+temp)/temp*temp;

                  if(tempx>a&&tempx<=c&&tempy>b&&tempy<=d)
                {
                    ans1=tempx;
                    ans2=tempy;


                    flag=1;
                    break;
                }


            }

            if(flag)
                break;
        }

         if(flag)
        {



            if(a<ans1&&ans1<=c&&ans2>b&&ans2<=d)
            {
                cout<<ans1<<" "<<ans2<<endl;
            }
            else
            {
                cout<<ans2<<" "<<ans1<<endl;

            }

        }
        else
        {
            cout<<-1<<" "<<-1<<endl;
        }

    }

    return 0;
}

相关文章:

  • 郑州新站网站推广工具/十大免费网站推广平台
  • 开通企业网站需要多少钱/关键词推广软件
  • 免费做app的网站有吗/如何制作企业网站
  • 建设文明网站平台的意义与概述/中国网评中国网评
  • 百度站长验证网站失败/友链出售
  • 商标设计网站免费/优化排名seo
  • C语言指针个人理解
  • 网络安全系统性学习路线「全文字详细介绍」
  • 你有一份奖学金,请注意查收~浙江财经大学 MBA奖学金
  • 手把手教你Linux的服务管理
  • 实验三 Windows窗体的设计及常用控件(1)
  • 【计算机毕业设计】java SpringBoot校园大学生志愿者服务系统
  • 【深入理解Kafka系列】第六章 __consumer_offsets(位移主题)
  • 脑机接口科普0008——侵入式与非侵入式
  • Nginx网站服务
  • Python游戏嗷大喵快跑设计
  • nginx负载均衡高可用部署
  • 【附源码】计算机毕业设计SSM怦然心动网上服装商城