若是全部数加起来是偶数那么必定能够,不然不行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; }
大意:每次选取一个起始点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; }
大意:每次选择两个叶子,路径上每一个点-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; }
大意:有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; }
大意:有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; }
大意:有一棵树,树上每一个点有石头,树上某个点有一个标记,每次能够扔掉有标记的点上的一块石头,而后挪到相邻点,若是某我的操做时这个标记没有石头,那么不合法
显然若是是个菊花,若是有个儿子的石头数小于根,那么先手放在根就赢了
对于通常的状况,咱们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; }