AtCoder Grand Contest 010 题解

A - Addition

如果奇数的个数是奇数就无解,否则就有解。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
int n, ans; 
 
int main()
{
	gi(n);
	for (int i = 1; i <= n; ++i)
	{
		int x = F();
		if (x & 1) ++ans;
	}
	if (ans & 1) puts("NO");
	else puts("YES");
}

  

B - Boxes

模拟,计算出以这个开头的操作有多少次,然后判断一下是不是可以完成。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
int64 n, a[100010], b[100010], x[100010];
 
int64 s = 0;
 
int main()
{
	gi(n);
	for (int i = 1; i <= n; ++i) gi(a[i]), s += a[i];
	if (s % ((n + 1LL) * n / 2) != 0)
	{
		puts("NO");
		return 0;
	}
	s /= ((n + 1LL) * n / 2);
	int64 all = s, allx = s * (n - 1);
	for (int i = 1; i <= n; ++i)
	{
		if ((s + a[i] - a[i % n + 1]) % n != 0)
		{
			puts("NO");
			return 0;
		}
		int64 y = (s + a[i] - a[i % n + 1]) / n;
		int64 x = s - y;
		if (y > all || x > allx)
		{
			puts("NO");
			return 0;
		}
		all -= y;
		allx -= x;
		b[i % n + 1] = y;
	}
	if (all || allx) return puts("NO"), 0;
	int64 cnt = 0, tag = 0;
	for (int i = 1; i <= n; ++i)
	{
		cnt += b[i];
		tag += cnt;
		x[i] += tag;
		if (x[i] > a[i])
		{
			puts("NO");
			return 0;
		}
	}
	for (int i = 1; i <= n; ++i)
	{
		cnt -= b[i];
		tag += cnt;
		if (b[i]) tag -= n * (b[i]);
		x[i] += tag;
		//cerr << x[i] << endl;
		if (x[i] != a[i])
		{
			puts("NO");
			return 0;
		}
	}
	puts("YES");
	return 0; 
}

  

C - Cleaning

对于每一个非叶节点,所有的覆盖都至少有一个端点在自己的子树里,要么两个都是,要么只有一个,计算一下情况,转移上去,判断即可。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
const int N = 1e5 + 10;
 
int n, deg[N];
 
int64 A[N];
 
VI edge[N];
 
void dfs(int u, int fa)
{
	if (deg[u] <= 1) return;
	int64 x = 0, cnt = 0, la = 0;
	for (auto v : edge[u])
	{
		if (v == fa) continue;
		dfs(v, u);
		x += A[v];
		la = max(la, A[v]);
	}
	cnt = min(x >> 1, x - la);
	if (x >= A[u] && x <= A[u] + cnt)
	{
		int64 c = x - A[u];
		A[u] -= c;
	}
	else
	{
		puts("NO");
		exit(0);
	}
}
 
int main()
{
	gi(n);
	for (int i = 1; i <= n; ++i) gi(A[i]);
	for (int i = 1; i < n; ++i)
	{
		int a, b;
		gii(a, b);
		edge[a].pb(b);
		edge[b].pb(a);
		++deg[a], ++deg[b];
	}
	if (n == 2)
	{
		puts(A[1] == A[2] ? "YES" : "NO");
		return 0;
	} 
	int root = 1;
	for (; deg[root] == 1; ++root);
	dfs(root, 0);
	if (!A[root]) puts("YES");
	else puts("NO");
}

  

D - Decrementing

如果不考虑除以gcd的问题,就是sigma(A[i])-n的奇偶来判断胜负,如果有gcd,但如果是奇数,先手肯定必胜,否则看看先手能不能想办法除以2改变奇偶。递归下去交换先后手到一个不能改变的状态就好了。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
const int N = 1e5 + 10;
 
int n, a[N];
 
void dfs(int x)
{
	long long s = 0;
	for (int i = 1; i <= n; ++i) 
		s += a[i] - 1;
	if (s & 1)
	{
		puts(x ? "Second" : "First");
		return;
	} 
	int cnt = 0;
	for (int i = 1; i <= n; ++i)
		if (a[i] & 1) ++cnt;
	for (int i = 1; i <= n; ++i)
		if (a[i] == 1) cnt = 233;
	if (cnt != 1)
	{
		puts(x ? "First" : "Second");
		return;
	}
	for (int i = 1; i <= n; ++i) 
		if (a[i] & 1) --a[i];
	int v = 0;
	for (int i = 1; i <= n; ++i) v = __gcd(v, a[i]);
	for (int i = 1; i <= n; ++i) a[i] /= v;
	dfs(x ^ 1);
}
 
int main()
{
	gi(n);
	for (int i = 1; i <= n; ++i) gi(a[i]);
	dfs(0);
}

  

E - Rearranging

我们发现不互质的数相对位置不会改变,那么建出图来,先按从小到大遍历出一个DAG,从大到小跑拓扑序即可。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
const int N = 2010;
 
int n, a[N], t[N][N], deg[N];
 
bool vis[N];
 
VI edge[N];
 
void dfs(int u)
{
	vis[u] = 1;
	for (int j = 1; j <= n; ++j)
		if (!vis[j] && t[u][j])
			edge[u].pb(j), ++deg[j], dfs(j);
}
 
priority_queue<int> pq;
 
int main()
{
	gi(n);
	for (int i = 1; i <= n; ++i) gi(a[i]);
	sort(a + 1, a + n + 1);
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			if (__gcd(a[i], a[j]) != 1)
				t[i][j] = 1;
	for (int i = 1; i <= n; ++i)
		if (!vis[i]) dfs(i);
	for (int i = 1; i <= n; ++i) if (!deg[i]) pq.push(i);
	while (!pq.empty())
	{
		int u = pq.top(); pq.pop();
		printf("%d ", a[u]);
		for (auto v : edge[u])
		{
			--deg[v];
			if (!deg[v]) pq.push(v);
		}
	}
	return 0;
}

  

F - Tree Game

我们发现只有a[u]>a[v]的(u,v)才能走,否则两个人来回最后还是在原点不能动,所以建出(a[u]>a[v])的图,必败态就是没有出边了,所以对于每个点O(n) dfs一下即可。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
const int N = 3010;
 
int n, a[N];
 
vector<int> edge[N];
 
bool dfs(int u, int fa)
{
	bool ret = 0;
	for (auto v : edge[u])
	{
		if (v == fa) continue;
		if (a[u] > a[v]) ret |= dfs(v, u) ^ 1;
	}
	return ret;
}
 
int main()
{
	gi(n);
	for (int i = 1; i <= n; ++i) gi(a[i]);
	for (int i = 1; i < n; ++i)
	{
		int u, v;
		gii(u, v);
		edge[u].pb(v);
		edge[v].pb(u);
	}
	for (int i = 1; i <= n; ++i) if (dfs(i, 0)) printf("%d ", i);
	return 0;
}

  

posted @ 2018-09-13 22:08  AnzheWang  阅读(139)  评论(0编辑  收藏  举报