【AtCoder】AGC010

AGC010

A - Addition

若是全部數加起來是偶數那麼必定能夠,不然不行node

#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('\n')
#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,循環加上一個等差數列,問可否達到目標狀態c++

事實上,這纔是我心目中的E,這場的BD異常難(B是對於它500的分數難了一點。。),EF異常水。。。spa

可是寫起來很好寫,首先判斷是否是\(\frac{N(N + 1) }{2}\)的整數倍code

假如這個倍數是k,而後每次至關於相鄰兩個數要麼差值是k,要麼差值是k - N排序

,k - 2N,k - 3N....,並且每次用的N的次數總和不超過krem

這是必要的,事實上也是充分的,充分性能夠拿程序檢驗,然而不檢驗也沒人管你,畢竟不是數學證實題get

#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('\n')
#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,每次在某個點處若是過多了就把兩個沒有閉合的路徑拼在一塊兒就好。。it

#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('\n')
#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,而後這些數同時除以他們的gcdio

若是全是奇數,先手必敗,若是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('\n')
#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('\n')
#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) {D異常難(B是對於它500的分數難了一點。。),EF異常水。。。

可是寫起來很好寫,首先判斷是否是    

的整數倍

假如這個倍數是k,而後每次至關於相鄰兩個
        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('\n')
#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;
}
相關文章
相關標籤/搜索