zoukankan      html  css  js  c++  java
  • 【AtCoder】AGC010

    AGC010

    A - Addition

    如果所有数加起来是偶数那么一定可以,否则不行

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 1000005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 +c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N;
    int t = 0;
    void Solve() {
        read(N);
        int a;
        for(int i = 1 ; i <= N ; ++i) {
    	read(a);
    	t += (a & 1);
        }
        t = t & 1;
        if(t == 0) puts("YES");
        else puts("NO");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    B - Boxes

    大意:每次选取一个起始点i,循环加上一个等差数列,问能否达到目标状态

    事实上,这才是我心目中的E,这场的BD异常难(B是对于它500的分数难了一点。。),EF异常水。。。

    但是写起来很好写,首先判断是不是(frac{N(N + 1) }{2})的整数倍

    假如这个倍数是k,然后每次相当于相邻两个数要么差值是k,要么差值是k - N

    ,k - 2N,k - 3N....,而且每次用的N的次数总和不超过k

    这是必要的,事实上也是充分的,充分性可以拿程序检验,然而不检验也没人管你,毕竟不是数学证明题

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 +c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N;
    int64 a[MAXN],s;
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) {
        	read(a[i]);
        	s += a[i];
        }
        int64 all = 1LL * N * (N + 1) / 2;
        if(s % all != 0) {puts("NO");return;}
        int64 k = s / all;
        int64 cnt = k;
        for(int i = 2 ; i <= N ; ++i) {
        	if(a[i] - a[i - 1] == k) continue;
        	int64 t = k - (a[i] - a[i - 1]);
        	if(t % N != 0 || t < 0) {puts("NO");return;}
        	cnt -= t / N;
        	if(cnt < 0) {puts("NO");return;}
        }
        puts("YES");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    C - Cleaning

    大意:每次选择两个叶子,路径上每个点-1,问能否变成全0

    就是极其简单的树dp,每次在某个点处如果过多了就把两个没有闭合的路径拼在一起就好。。

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 +c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    struct node {
        int to,next;
    }E[MAXN * 2];
    int N,head[MAXN],sumE,deg[MAXN];
    int64 up[MAXN],A[MAXN];
    bool flag = 0;
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    void dfs(int u,int fa) {
        if(deg[u] == 1) {up[u] = A[u];return;}
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    dfs(v,u);
    	    if(flag) return;
    	}
        }
        int64 md = 0;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    md = max(up[v],md);
    	    up[u] += up[v];
    	}
        }
        if(up[u] == 0 && A[u] == 0) return;
        int64 k = min(up[u] / 2,up[u] - md);
        if(up[u] - k > A[u] || up[u] < A[u]) {flag = 1;return;}
        up[u] = A[u] - (up[u] - A[u]);
    }
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) read(A[i]);
        int a,b;
        for(int i = 1 ; i < N ; ++i) {
    	read(a);read(b);
    	deg[a]++;deg[b]++;
    	add(a,b);add(b,a);
        }
        if(N == 2) {
    	if(A[1] == A[2]) puts("YES");
    	else puts("NO");
    	return;
        }
        int rt = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	if(deg[i] > 1) rt = i;
        }
        dfs(rt,0);
        if(flag == 1 || up[rt] != 0) puts("NO");
        else puts("YES");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    D - Decrementing

    大意:有N个互质的数,每次可以选择一个数-1,然后这些数同时除以他们的gcd

    如果全是奇数,先手必败,如果111111先手必败,否则先手可以造出一个偶数来,且除过gcd后奇偶性不变,则后手把那个偶数改成奇数即可

    如果只有奇数个偶数,先手必胜

    如果有偶数个偶数,且奇数至少有两个,那么先手必败

    如果有偶数个偶数,奇数有一个,那么先手必须取动那个奇数,模拟到可以判断胜负的时刻即可

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
        	if(c == '-') f = -1;
        	c = getchar();
        }
        while(c >= '0' && c <= '9') {
        	res = res * 10 +c - '0';
        	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N,A[MAXN];
    int gcd(int a,int b) {
        return b == 0 ? a : gcd(b,a % b);
    }
    int check() {
        int c = 0,t;
        for(int i = 1 ; i <= N ; ++i) {
            if(A[i] & 1) {++c;t = A[i];}
        }
        if((N - c) & 1) return 1;
        if(c >= 2 || t == 1) return 0;
        return -1;
    }
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) {
            read(A[i]);
        }
        int cnt = 0;
        while(1) {
            int x = check();
            if(x != -1) {
                if((x ^ cnt) == 1) puts("First");
                else puts("Second");
                return;
            }
            cnt ^= 1;
            int g = 0;
            for(int i = 1 ; i <= N ; ++i) {
                if(A[i] & 1) --A[i];
                g = gcd(g,A[i]);
            }
            for(int i = 1 ; i <= N ; ++i) {
                A[i] /= g;
            }
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    E - Rearranging

    大意:有N个数,第一个人可以任意重排,第二个人可以随便交换互质的两个数,第一个人希望字典序最小,第二个人希望字典序最大,问最后的序列

    这个就是如果不互质建出一张图,标出层号,起始层号都是0,然后我们从小到大搜索,把这个点相邻的层号都标成这个点的层+1,找层号+1最小的点开始搜(并不一定搜到所有的儿子,因为可能搜完某个儿子后另外的儿子层号已经变了)

    然后合并两个序列就是哪个大哪个放前面,类似归并排序

    然后最后的序列就是我们想要的

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 2005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
        	if(c == '-') f = -1;
        	c = getchar();
        }
        while(c >= '0' && c <= '9') {
        	res = res * 10 +c - '0';
        	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    struct node {
        int to,next;
    }E[MAXN * MAXN * 2];
    int head[MAXN],sumE,A[MAXN],N;
    int dfn[MAXN];
    bool vis[MAXN];
    vector<int> L;
    int gcd(int a,int b) {
        return b == 0 ? a : gcd(b,a % b);
    }
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    vector<int> Merge(vector<int> a,vector<int> b) {
        vector<int> c;
        int pa = 0,pb = 0;
        while(pa < a.size() && pb < b.size()) {
            if(a[pa] > b[pb]) c.pb(a[pa++]);
            else c.pb(b[pb++]);
        }
        while(pa < a.size()) c.pb(a[pa++]);
        while(pb < b.size()) c.pb(b[pb++]);
        return c;
    }
    vector<int> Calc(int u) {
        vector<int> son;
        vis[u] = 1;
        for(int i = head[u] ; i ; i = E[i].next) {
            int v = E[i].to;
            if(!vis[v]) son.pb(v);
        }
        sort(son.begin(),son.end());
        vector<int> tmp;
        for(auto t : son) dfn[t] = dfn[u] + 1;
        for(auto t : son) {
            if(!vis[t] && dfn[t] == dfn[u] + 1) {
                tmp = Merge(tmp,Calc(t));
            }
        }
        tmp.insert(tmp.begin(),A[u]);
        return tmp;
    }
    
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) read(A[i]);
        sort(A + 1,A + N + 1);
        for(int i = 1 ; i <= N ; ++i) {
            for(int j = i + 1 ; j <= N ; ++j) {
                if(gcd(A[i],A[j]) != 1) {
                    add(i,j);add(j,i);
                }
            }
        }
        for(int i = 1 ; i <= N ; ++i) {
            if(dfn[i] == 0) {
                L = Merge(Calc(i),L);
            }
        }
        for(auto t : L) {
            out(t);space;
        }
        enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    F - Tree Game

    大意:有一棵树,树上每个点有石头,树上某个点有一个标记,每次可以扔掉有标记的点上的一块石头,然后挪到相邻点,如果某个人操作时这个标记没有石头,那么不合法

    显然如果是个菊花,如果有个儿子的石头数小于根,那么先手放在根就赢了

    对于一般的情况,我们dp,对于一个根,如果他的儿子是先手必胜,那么不能移动到那个儿子,我们就是在先手必败的儿子中找有没小于根节点的石头值的点,如果有的话以这个点为根就是先手必胜

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 3005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 +c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    struct node {
        int to,next;
    }E[MAXN * 2];
    int N,head[MAXN],sumE;
    int64 A[MAXN],rem[MAXN];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    bool dfs(int u,int fa) {
        int64 s = 0;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    if(!dfs(v,u)) {
    		if(A[u] > A[v]) return true;
    	    }
    	}
        }
        return false;
        
    }
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) read(A[i]);
        int a,b;
        for(int i = 1 ; i < N ; ++i) {
    	read(a);read(b);
    	add(a,b);add(b,a);
        }
        int ans = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	if(dfs(i,0)) {out(i);space;}
        }
        enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    Go语言基础--1.1 变量的声明
    基本语法
    弹性盒子修改
    弹性盒子内容
    弹性盒子
    响应式列重置
    栅格系统
    布局容器
    额外按钮
    可消失的弹出框
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10844588.html
Copyright © 2011-2022 走看看