AcWing 每日一题 2022.5.1

周日些周六AcWing周赛的三道题。
A 签到题

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

int n, k;
int w[10];

int main() {
	scanf("%d %d", &n, &k);
	for (int i = 1; i <= n; i++) {
		int tmp;
		scanf("%d", &tmp);
		w[tmp]++;
	}

	int ans = 0;
	for (int i = 0; i <= 5 - k; i++) {
		ans += w[i];
	}

	cout << ans / 3 << endl;

	return 0;
}

B
贪心算法 对于边界处理以及STL稍微复杂。STL中vector等size得出的类型不是int,和int做运算会出现段错误Segment Fault,需要先进行类型转换。

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

vector<int> v;
int n;
int ans = 0;
int odd1 = 0, odd2 = 0;

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		int tmp;
		scanf("%d", &tmp);

		if (tmp % 2 != 0) {
			v.push_back(tmp);
			if (tmp < 0)
				odd1++;
			else
				odd2++;
		} else {
			if (tmp > 0)
				ans += tmp;
		}
	}

	sort(v.begin(), v.end());

	if (odd2 == 0) {
		ans += v[v.size() - 1];
	} else {
		if (odd2 % 2 != 0) {
			for (int i = v.size() - 1; i >= (int)v.size() - odd2; i--)
				ans += v[i];
		} else {
			if (odd2 != 0) {
				for (int i = v.size() - 1; i >= (int)v.size() - odd2 + 1; i--)
					ans += v[i];
				if (odd1 > 0 && v[v.size() - odd2] > abs(v[v.size() - odd2 - 1]))
					ans += v[v.size() - odd2] + v[v.size() - odd2 - 1];
			}
		}
	}

	cout << ans << endl;

	return 0;
}

C
染色法 详细注释在代码中

  1. 对于整个图来说,每个联通块的取值之间互相不影响,
    所以最终答案为每个连通块取值的乘积。
  2. 对于单个连通块来说,如果该连通块是二分图,则有解,
    否则无解。
  3. 对于有解的情况,设二分图两个点集中点数分别为x、y
    由于奇数有1、3两个赋值选择,偶数只有2一个选择,所以,
    一个二分图的赋值可能结果为 2^x + 2^y 。
#include <bits/stdc++.h>
using namespace std;

const int N = 3e5 + 10, M = 2 * N, mod = 998244353;

typedef long long LL;

/*
1. 对于整个图来说,每个联通块的取值之间互相不影响,
所以最终答案为每个连通块取值的乘积。
2. 对于单个连通块来说,如果该连通块是二分图,则有解,
否则无解。
3. 对于有解的情况,设二分图两个点集中点数分别为x、y
由于奇数有1、3两个赋值选择,偶数只有2一个选择,所以,
一个二分图的赋值可能结果为 2^x + 2^y 。

*/

int n, m;
int h[N], e[M], ne[M], idx;
int col[N];
int s1, s2;

void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

int pow2(int x) {
	int res = 1;
	while (x -- )
		res = res * 2 % mod;
	return res;
}

// 染色法,只会给连通图染色
bool dfs(int u, int c) {
	col[u] = c;
	if (c == 1)
		s1++;
	else
		s2++;

	for (int i = h[u]; ~i; i = ne[i]) {
		int j = e[i];
		if (col[j] && col[j] != 3 - c)
			return false;
		if (!col[j] && !dfs(j, 3 - c))
			return false;
	}
	return true;
}

int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		scanf("%d %d", &n, &m);

		// 小Trick,如果是 sizeof h, sizeof col的话会超时
		// 这样只memset本次需要的部分,可以节省时间
		// memset函数第三个参数为字节数
		memset(h, -1, (n + 1) * 4);
		memset(col, 0, (n + 1) * 4);
		idx = 0;

		while (m--) {
			int a, b;
			scanf("%d %d", &a, &b);
			add(a, b), add(b, a);
		}

		int res = 1;
		for (int i = 1; i <= n; i++) {
			// 染色法自动,只会给连通图染色。
			if (!col[i]) {
				s1 = s2 = 0;
				if (dfs(i, 1))
					res = (LL)res * (pow2(s1) + pow2(s2)) % mod;
				else {
					res = 0;
					break;
				}
			}
		}

		printf("%d\n", res);
	}

	return 0;
}
posted @ 2022-05-01 15:00  superPG  阅读(23)  评论(0编辑  收藏  举报