当前位置:网站首页>Codeforces Round #717 (Div. 2)

Codeforces Round #717 (Div. 2)

2022-06-27 19:14:00 我的故事用酒换

2021.4.21

A

题意:给两个数n和k,然后输入含有n个数的序列,每次对序列进行操作:取两个数,其中一个加1,另一个减1,并且保证序列中的每个数都是非负数。对该序列最多进行k次操作,使得该序列形成一个最小的字典序。(题目看成取的两个数需要大小不同,一直wa,结果这场就炸了,)

题解:每次操作对第一个非0的数-1,最后一个数+1,进行k次操作,如果序列除了最后一个数其他都是0,那就可以直接退出操作,已经达到最大的字典序了。

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int t,n,k,a[105];
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        int l=1,r=n;
        while(k)
        {
            if(a[l]>=k)
            {
                a[r]+=k;
                a[l]-=k;
                k=0;
            }
            else
            {
                a[n]+=a[l];
                k-=a[l];
                a[l]=0;
                l++;

            }
            if(l==r)
                break;
        }
        for(int i=1;i<=n;i++)
            cout<<a[i]<<' ';
        cout<<endl;
    }
    return 0;
}

B

题意:给一个数n,然后是一个含有n个数的序列,可以将相邻的两个数进行异或和(当时看成按位或┭┮﹏┭┮),然后序列的长度就-1,因为两个数异或成一个数了。最后判断变化后的序列是否可以成为一个每个数都是一样的序列,要求最后生成满足条件的序列至少长度为2。

题解:①x^x=0 ②x^x^x=x

先求整个序列的异或和,如果为0,根据①可得序列可以分成异或和相等的两段序列,若不为0,根据③遍历前k(k<n)个数的异或和是否等于整个序列的异或和,如果等于就判断((k+1)到(n-1))前缀异或和是否有等于0,有就直接可以将整个序列分成异或和相等的三段序列。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
    ll t,n,a[2005];
    cin>>t;
    while(t--)
    {
        cin>>n;
        a[0]=0;
        int p=0;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            a[i]^=a[i-1];
        }
        if(a[n]==0)
        {
            cout<<"YES"<<endl;
            continue;
        }
        int flag=1;
        for(int i=1;i<n;i++)
        {
            if(a[i]==a[n])
            {
                for(int j=i+1;j<n;j++)
                {
                    if(!a[j])
                    {
                        cout<<"YES"<<endl;
                        flag=0;
                        break;
                    }
                }
            }
            if(!flag)
                break;
        }
        if(flag)
            cout<<"NO"<<endl;
    }
}

C

题意:给一个长度为n的序列,判断这个序列是否可以分成和相等的两组序列,如果能,需要最少在序列中删除几个数字使得序列不符合条件,并且列出删除数字的下标。

题解:先去算出整个序列的最大公因子,然后序列的每个数都除以最大公因子,缩小范围,这样得到的序列必会有奇数出现,并且得到的结果与原序列是一样的

①序列和为奇数,必不可能分成两组和相等的序列,需删除0个数字。

②序列和为偶数但序列和/2 得到的数不能由这n个序列随意组合相加得到,那也无法分成两组和相等的序列,需删除0个数字。

③序列和为偶数,只需删除序列里的某一个奇数使得序列和成为奇数,然后得到①

#include <bits/stdc++.h>
int dp[200005],a[105];
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    int n,d,sum=0;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(i==1)
            d=a[i];
        else
            d=gcd(d,a[i]);
    }
    for(int i=1;i<=n;i++){
        a[i]/=d;
        sum+=a[i];
    }
    int k=0;
    dp[0]=1;
    for(int i=1;i<=n;i++)
    {
        if(a[i]%2)
            k=i;
        for(int j=sum;j>=a[i];j--)
        {
            dp[j]|=dp[j-a[i]];
        }
    }
    if(sum%2||!dp[sum/2])
        cout<<0<<endl;
    else
        cout<<1<<endl<<k<<endl;
    return 0;
}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

打完人没了。。。。。。

原网站

版权声明
本文为[我的故事用酒换]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_46113968/article/details/116029067