咱們確定能夠獲得這些數的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(); }