zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    装饰器和迭代器
    闭包函数
    函数对象
    Python函数
    函数的基本使用
    文件处理
    量化策略
    Android--生命周期
    算法转AI平台工程师记录-0
    python3.6安装
  • 原文地址:https://www.cnblogs.com/AnzheWang/p/9643564.html
Copyright © 2011-2022 走看看