咱们确定能够获得这些数的gcd,而后判断每一个数减整数倍的gcd可否获得Knode
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; 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,K; int a[MAXN],g; int gcd(int a,int b) { return b == 0 ? a : gcd(b,a % b); } void Solve() { read(N);read(K); for(int i = 1 ; i <= N ; ++i) { read(a[i]); g = gcd(a[i],g); } for(int i = 1 ; i <= N ; ++i) { if(a[i] >= K && (a[i] - K) % g == 0) { puts("POSSIBLE"); return; } } puts("IMPOSSIBLE"); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
对于初始的喜好度答案,若是咱们不把含有个数最多的比赛ban掉,答案永远不会降低,因此咱们试试一次次ban掉人数最多的比赛,取每次最小值c++
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; 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,M; int a[305][305],ans; int cnt[305],pos[305]; bool vis[305]; void Solve() { read(N);read(M); for(int i = 1 ; i <= N ; ++i) { for(int j = 1 ; j <= M ; ++j) { read(a[i][j]); } } for(int i = 1 ; i <= N ; ++i) {cnt[a[i][1]]++;pos[i] = 1;} for(int i = 1 ; i <= M ; ++i) ans = max(ans,cnt[i]); for(int k = 1 ; k < M ; ++k) { int t = 1; for(int j = 1 ; j <= M ; ++j) { if(cnt[j] > cnt[t]) t = j; } vis[t] = 1; for(int i = 1 ; i <= N ; ++i) { cnt[a[i][pos[i]]]--; while(vis[a[i][pos[i]]]) {++pos[i];} cnt[a[i][pos[i]]]++; } int tmp = 0; for(int j = 1 ; j <= M ; ++j) { tmp = max(tmp,cnt[j]); } ans = min(ans,tmp); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
把每一个金币变成\((A_{i} - C_{i},B_{i} - C{i},0)\),而后总贡献加上全部\(C[i]\)
按照\(A[i] - B[i]\)排序,而后枚举一个中间点K,在K里面选\(B[i] - C[i]\)最大的Y个,在后面选\(A[i] - C[i]\)最大的\(X\)个,取最小值spa
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; 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 X,Y,Z; int64 A[MAXN],B[MAXN],C[MAXN],ans,f[MAXN],b[MAXN]; int id[MAXN]; multiset<int64> S; void Solve() { read(X);read(Y);read(Z); for(int i = 1 ; i <= X + Y + Z ; ++i) { read(A[i]);read(B[i]);read(C[i]); ans += C[i]; A[i] -= C[i];B[i] -= C[i]; id[i] = i; } sort(id + 1,id + X + Y + Z + 1,[](int a,int b){return A[a] - B[a] < A[b] - B[b];}); int64 all = 0; for(int i = 1 ; i <= X + Y + Z ; ++i) { S.insert(B[id[i]]); all += B[id[i]]; if(S.size() > Y) { all -= *(S.begin()); S.erase(S.begin()); } f[i] = all; } S.clear();all = 0; for(int i = X + Y + Z ; i >= 1 ; --i) { S.insert(A[id[i]]); all += A[id[i]]; if(S.size() > X) { all -= *(S.begin()); S.erase(S.begin()); } b[i] = all; } int64 tmp = f[Y] + b[Y + 1]; for(int i = Y + 1; i <= Y + Z ; ++i) { tmp = max(tmp,f[i] + b[i + 1]); } out(ans + tmp);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
熟练选手直接分析每条边可否取到最大贡献
每条边最大贡献是二倍的它断开后分红子树的较小的子树大小
若是是哈密顿回路,这个贡献显然能够经过求一个重心构造出来
哈密顿路分析一下,只和起点有关,和起点逐步往子树扩大的方向走,扩大到至少大小为\(\frac{N}{2}\)时所通过的边权和,就是咱们要扣除的
若是有一条边能够把子树断成\(\frac{N}{2}\),那么减小的必定是这条边,不然其余状况都要通过这条边
不然求一个重心,找和重心相连的边最小的,其余状况必定包含一条和重心相连的边code
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; 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;int64 val; }E[MAXN * 2]; int N,sumE,head[MAXN],siz[MAXN],son[MAXN],dep[MAXN],fa[MAXN]; int64 ans; void add(int u,int v,int64 c) { E[++sumE].to = v; E[sumE].next = head[u]; E[sumE].val = c; head[u] = sumE; } void dfs(int u) { siz[u] = 1; dep[u] = dep[fa[u]] + 1; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa[u]) { fa[v] = u; dfs(v); siz[u] += siz[v]; son[u] = max(siz[v],son[u]); ans += min(siz[v],N - siz[v]) * 2 * E[i].val; } } son[u] = max(son[u],N - siz[u]); } void Solve() { read(N); int a,b;int64 c; for(int i = 1 ; i < N ; ++i) { read(a);read(b);read(c); add(a,b,c);add(b,a,c); } dfs(1); int t = 1; for(int i = 2 ; i <= N ; ++i) { if(son[i] < son[t] || (son[i] == son[t] && dep[i] > dep[t])) t = i; } if(N % 2 == 0 && son[t] == N / 2) { for(int i = head[t] ; i ; i = E[i].next) { if(E[i].to == fa[t]) ans -= E[i].val; } } else { int64 k = 0x7fffffff; for(int i = head[t] ; i ; i = E[i].next) { k = min(k,E[i].val); } ans -= k; } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
问网格图中某一矩形区域到顶点的和
竟然是能够\(O(1)\)统计的,感受很是长知识排序
具体怎么\(O(1)\)呢get
问\((0,0)\)点到\((x,y)\)点的方案数,是\(\binom{x + y}{y}\)it
记为\(W(x,y)\)class
就是\(\sum_{i = 0}^{y}W(x,i) = W(x + 1,y)\)date
就是在选\(x,i\)往右走一步,而后就一直往上走gc
\(\sum_{i = 0}^{x}\sum_{j = 0}^{y} W(i,j) = W(x + 1,y + 1) - 1\)
由于横竖同理,咱们能够把每一个都合成\(W(i + 1,y)\),少一个\(W(0,y)\),因此-1
这样咱们求一个区域的值
\(\sum_{i = x_{1}}^{x_{2}}\sum_{j = y_{1}}^{y_{2}} W(x_{2} + 1,y_{2} + 1) - W(x_{1},y_{2} + 1) - W(x{2} + 1,y_{2}) + W(x_{1},y_{1})\)
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 1000005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; 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); } const int MOD = 1000000007; const int V = 2000005; int X[7],Y[7],ans,fac[V + 5],invfac[V + 5]; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } void update(int &x,int y) { x = inc(x,y); } int fpow(int x,int c) { int res = 1,t = x; while(c) { if(c & 1) res = mul(res,t); t = mul(t,t); c >>= 1; } return res; } int C(int n,int m) { if(n < m) return 0; return mul(fac[n],mul(invfac[m],invfac[n - m])); } int W(int x,int y) { return C(x + y,x); } int way1(int x,int y) { int s1 = x - X[2],s2 = x - X[1]; int t1 = y - Y[2],t2 = y - Y[1]; return inc(inc(W(s2 + 1,t2 + 1),W(s1,t1)),MOD - inc(W(s2 + 1,t1),W(s1,t2 + 1))); } int way2(int x,int y) { int s1 = X[5] - x,s2 = X[6] - x; int t1 = Y[5] - y,t2 = Y[6] - y; return inc(inc(W(s2 + 1,t2 + 1),W(s1,t1)),MOD - inc(W(s2 + 1,t1),W(s1,t2 + 1))); } void Solve() { fac[0] = 1; for(int i = 1 ; i <= V ; ++i) fac[i] = mul(fac[i - 1],i); invfac[V] = fpow(fac[V],MOD - 2); for(int i = V - 1 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1); for(int i = 1 ; i <= 6 ; ++i) read(X[i]); for(int i = 1 ; i <= 6 ; ++i) read(Y[i]); for(int i = X[3] ; i <= X[4] ; ++i) { update(ans,mul(MOD - (i + Y[3] - 1),mul(way1(i,Y[3] - 1),way2(i,Y[3])))); update(ans,mul(i + Y[4],mul(way1(i,Y[4]),way2(i,Y[4] + 1)))); } for(int j = Y[3] ; j <= Y[4] ; ++j) { update(ans,mul(MOD - (X[3] - 1 + j),mul(way1(X[3] - 1,j),way2(X[3],j)))); update(ans,mul(j + X[4],mul(way1(X[4],j),way2(X[4] + 1,j)))); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
显然若是两个点在两棵树里儿子的奇偶性不一样,必定误解
不然把两棵树建出一个无向图,而后若是两个点都有偶数个儿子,那么连一条边,再建一个点,把两棵树的树根都连在上面
求一个欧拉回路,那么若是从第一棵树到第二棵树,那么这个点就是1,不然就是-1
这样的道理是什么呢。。。能够从底向上概括,显然两棵树的叶子点有两条边,出度和入度相等,给叶子上填上相应的数,而后叶子指向父亲的至关于把+1或-1贡献给父亲,从底向上概括也行
在学完选修2-2以后,我能够把这个解释为,进行合情推理后,发现是对的= =
#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 MAXN 100005 #define eps 1e-12 //#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 A[MAXN],B[MAXN],s[MAXN][2],ans[MAXN]; struct node { int to,next; }E[MAXN * 10]; int head[MAXN * 2],sumE = 1; bool vis[MAXN * 10]; void add(int u,int v) { E[++sumE].to = v; E[sumE].next = head[u]; head[u] = sumE; } void euler_road(int u) { for(int &i = head[u] ; i ; i = E[i].next) { int w = i; if(!vis[w]) { vis[w] = vis[w ^ 1] = 1; int v = E[w].to; if(u != 2 * N + 1 && v != 2 * N + 1 && abs(u - v) == N) { if(u < v) ans[u] = 1; else ans[v] = -1; } euler_road(v); } } } void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) { read(A[i]); if(A[i] != -1) { add(i,A[i]);add(A[i],i); s[A[i]][0]++; } else { add(i,2 * N + 1);add(2 * N + 1,i); } } for(int i = 1 ; i <= N ; ++i) { read(B[i]); if(B[i] != -1) { add(i + N,B[i] + N);add(B[i] + N,i + N); s[B[i]][1]++; } else { add(i + N,2 * N + 1);add(2 * N + 1,i + N); } } for(int i = 1 ; i <= N ; ++i) { if((s[i][0] ^ s[i][1]) & 1) { puts("IMPOSSIBLE"); return; } if(s[i][0] % 2 == 0) { add(i,i + N);add(i + N,i); } } puts("POSSIBLE"); euler_road(1); for(int i = 1 ; i <= N ; ++i) { out(ans[i]);space; } enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }