码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #717 (Div. 2) A B C 题解

时间:2021-04-22 16:23:39      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:元素   暴力枚举   mes   amp   code   algo   fine   --   break   

A Tit for Tat

题意:给你一个n个数的数组,在k次操作下,每次可以选2个数,一个+1,一个-1,求如何让数组前面的数最小,后面的数最大。最小不能为0.
思路:模拟,把前面的数-掉都加在最后一个数上

#include<iostream>
using namespace std;
int n,k;
int s[110];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&n,&k);
		
		for(int i=1;i<=n;i++) scanf("%d",&s[i]);
		
		int j=1;
		while(k)
		{
			if(j==n) break;
			if(s[j]>k) 
			{
				s[j]-=k;
				s[n]+=k;
				k=0;
			}
			else 
			{
			s[n]+=s[j];
			k-=s[j];
			s[j]=0;
			j++;
			}
		}
		
		for(int i=1;i<=n;i++) printf("%d ",s[i]);
		printf("\n");
	} 
	return 0; 
}

B AGAGA XOOORRR

题意:给你n个数的数组,每次选取两个相邻的元素;然后移除它们,并在它们的位置放置一个整数等于这2个数的异或和,求是否能使数组的所有元素相等。并且至少留下2个元素。
思路:首先,一定要注意看是相邻
先发掘一下性质
1 最后不是2个相等的数就是3个相等的数
因为4个相等的数等于2个相等的数
2 相邻的数选
那么分别暴力枚举2个分割点和1个分割点
然后取异或和看看想不相等
查询的时候可以用前缀和来查询 o1
总体时间复杂度 otn^2 = 6e7

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 20010;

int n, m;
int g[N];
int s[N];

int main() 
{
    int T;
    cin >> T;
    while (T -- ) 
    {
        cin >> n;
        for (int i = 1; i <= n; i ++ ) 
            cin >> g[i];
        
        s[1] = g[1];
        for (int i = 2; i <= n; i ++ ) 
            s[i] = s[i - 1] ^ g[i];

        bool flag = false;
        for (int i = 1; i <= n - 1; i ++ ) 
            if (s[i] == (s[n] ^ s[i])) 
            {
                flag = true;
                break;
            }

        for (int i = 1; i <= n - 1; i ++ ) 
            for (int j = i + 1; j <= n - 1; j ++ ) 
                if (s[i] == (s[j] ^ s[i]) && s[i] == (s[n] ^ s[j]))  
                {
                    flag = true;
                    break;
                }

        if (flag) puts("YES");
        else puts("NO");
    }

    return 0;
}

C Baby Ehab Partitions Again

题意:给你一个n个数的数组,求这个数组是否有2个序列,这2个序列必须包含这所有的n个数,并且每个数只包含一次,顺序随意。
并且定义,如果第一个子序列中元素的和等于第二个子序列中元素的和,则称这个数组是好的,
求是否可以通过删除最多一个数的情况下,使得它成为好的数组
思路:总和是ans的情况下 如果一开始不能表示出来 ans / 2的话 就输出0, 如果可以表示出来的话 就求暴力枚举删除的那一个数a[i],因为最多只删除一个数,然后看如果还是不能表示出来的话 直接输出break,当然前提是ans或者是ans-a[i] 必须是偶数 要不然也直接输出
能不能表示出来可以用01背包,每次判断选与不选,
总体时间复杂度 o n^2m = 2e7
m为数组总和

#include<bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define re register int
#define x first
#define y second
typedef long long ll ;
using namespace std;
const int N =  1e6 + 10 , inf = 0x3f3f3f3f , mod = 1e9 + 7 ;
int n , m ;
int f[N] ;
int a[N] ;
int main()
{
    cin >> n ;
    int ans = 0 ;
    for(int i = 1 ; i <= n ; i ++) 
    {
        cin >> a[i] ;
        ans += a[i] ;
    }
    f[0] = 1 ;
    for(int i = 1 ; i <= n ; i ++)
    {
        for(int j = ans ; j >= a[i] ; j --)
        {
            if(f[j-a[i]] && !f[j])
            {
                f[j] = true ;
            }
        }
    }
    
    if(!f[ans/2] || ans % 2 != 0) puts("0");
    else 
    {
        for(int k = 1 ; k <= n ; k ++)
        {
            memset(f,0,sizeof f) ;
            f[0] = 1 ;
            for(int i = 1 ; i <= n ; i ++)
            {
                if(i == k) continue ;
                for(int j = ans ; j >= 1 ; j --)
                {
                    if(!f[j] && f[j-a[i]])
                    {
                        f[j] = true ;
                    }
                }
            }
            if(!f[(ans-a[k]) / 2] || (ans - a[k]) % 2 != 0) 
            {
                cout << 1 << endl;
                cout << k << endl;
                break;
            }
        }
    }
    return 0 ;
}

Codeforces Round #717 (Div. 2) A B C 题解

标签:元素   暴力枚举   mes   amp   code   algo   fine   --   break   

原文地址:https://www.cnblogs.com/yueshehanjiang/p/14687619.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!