Codeforces Round #664 (Div. 2)

A题:https://codeforces.ml/contest/1395/problem/A

思路:当4个数里只有1个或0个奇数的时候,才能构成回文。题意给的操作是将前3个数分别减1,最后一个数加3,如果进行两次操作则加减的都是一个偶数,也就意味着不影响原来4个数的奇偶性。那么我们只需要进行一次操作即可。

#include <bits/stdc++.h>
using namespace std;
int main(int argc, char const *argv[])
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int r,g,b,w;
		int ans = 0;
		scanf("%d %d %d %d",&r,&g,&b,&w);
		if (r % 2 == 1) ans ++;
		if (g % 2 == 1) ans ++;
		if (b % 2 == 1) ans ++;
		if (w % 2 == 1) ans ++;
		if (ans <= 1) printf("Yes\n");
		else
		{
			if (r == 0 || g == 0 || b == 0) printf("No\n");
			else
			{
				r-=1;
				g-=1;
				b-=1;
				w+=3;
				ans = 0;
				if (r % 2 == 1) ans ++;
				if (g % 2 == 1) ans ++;
				if (b % 2 == 1) ans ++;
				if (w % 2 == 1) ans ++;
				if (ans <= 1) printf("Yes\n");
				else printf("No\n");
			}
		}
	}
	return 0;
}

B题:https://codeforces.ml/contest/1395/problem/B

写的时候当成“兵”写了,按蛇形一直输出,然后wa得生活不能自理,虽然也是能过的但是代码冗长,导致后面缝缝补补让我及其头疼。然后看了大佬的代码,,,orz

#include <bits/stdc++.h>
using namespace std;
int n,m,a,b;
int print(int x,int y)
{
	printf("%d %d\n",x,y);
	for (int i = 1; i <=m; ++i) if (i != y) printf("%d %d\n",x,i);
	return y == m ? m-1 : m;
}
int main(int argc, char const *argv[])
{
	scanf("%d%d%d%d",&n,&m,&a,&b);
	b = print(a,b);
	for (int i = 1; i <= n; ++i)
	{
		if (i == a) continue;
		b = print(i,b);
	}
	return 0;
}

  思路就是每一行都从这一行的第一个输出,将这一行输出完之后返回结束处的列下标,然后进入下一行。真是简洁明了。

C题:https://codeforces.ml/contest/1395/problem/C

比赛的时候没时间写了,都是b害的啊......

最后的ans是由n个c做或运算得到的。首先我们要知道按位或,有1取1,意思就是a|b的结果一定大于等于a和b的最大值,那我们将ans与n个c里的任意一个做或运算,其结果必须为ans,那暴力跑每一个ans,让每个ci都跟ans做一次或运算就能找到我们要的ans了。

#include <bits/stdc++.h>
using namespace std;
int n,m,a[211],b[211];
int check(int x)
{
	for (int i = 1; i <=n; ++i)
	{
		bool flag = 0;
		for (int j = 1; j <=m; ++j)
		{
			if (((a[i] & b[j]) | x) == x)
			{
				flag = 1;
				break;
			}
		}
		if (!flag) return 0;
	}
	return 1;
}
int main(int argc, char const *argv[])
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for(int j = 1; j <= m; j++) scanf("%d", &b[j]);
	for(int i = 0; i <= 511; i++) 
		if(check(i)) printf("%d\n", i), exit(0);
	return 0;
}

 D题:https://codeforces.ml/contest/1395/problem/D

思路:求出前缀和,暴力取了几天大于m,维护ans即可。

代码中第二个for循环获取大于m和小于m的分界线

第三for计算前缀和

第4个for中,每取一个大于m就要减去m天,故n/(d+1)是指n天里最多能取几个m,n-cnta是指着n天里总共有几天大于m,两者取一个较小值就是我们暴力的范围。

取了i天n-(d+1)*i得到还剩下的天数。

最后qzh[n] - qzh[n-i] + qzh[cnta] - qzh[max(cnta - g,0)]是指,取i个大于m天就得到qzh[n] - qzh[n-i] ,然后要扣除d*i天,由于是排序的肯定从前往后扣,那就是qzh[cnta] - qzh[max(cnta - g,0)],其中qzh[cnta]是前面小于m的总和,qzh[max(cnta - g,0)]是指当剩下的天数>小于m的天数的时候,那么去掉的天数可以是>m的那一部分,所以这里直接是0,当剩下的天数<小于m的天数的时候,则要从小于m的天里扣除。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,d,a[100011],cnta;
ll ans,qzh[100011];
int main(int argc, char const *argv[])
{
	scanf("%d%d%d",&n,&d,&m);
	for (int i = 1; i <=n; ++i) scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	for(int i = 1; i <= n; i++) if(a[i] <= m) cnta = i;
	if(cnta != n) --n;
	for(int i = 1; i <= n; i++) qzh[i] = qzh[i - 1] + a[i];
	for(int i = 0; i <= min(n / (d + 1), n - cnta); i++) {
		int g = n - (d + 1) * i;
		ans = max(ans, qzh[n] - qzh[n - i] + qzh[cnta] - qzh[max(cnta - g, 0)]);
	}
	printf("%lld\n", ans + a[n + 1]);
	return 0;
}

 

posted @ 2020-08-14 22:35  DemonSlayer  阅读(150)  评论(0编辑  收藏  举报