• 【AtCoder】ARC105


    ARC105

    来了,老年选手感到自己水平有一点差劲

    A - Fourtune Cookies

    题意:给四块饼干问能不能分成总和相同的两份

    二进制枚举就行

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    
    #define pii pair<int,int>
    typedef long long int64;
    using namespace std;
    
    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 a[10];
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	int sum = 0;
    	for(int i = 0 ; i < 4 ; ++i) {
    		read(a[i]);
    		sum += a[i];
    	}
    	for(int S = 1 ; S < (1 << 4) ; ++S) {
    		int s = 0;
    		for(int i = 0 ; i < 4 ; ++i) {
    			if(S & (1 << i)) s += a[i];
    		}
    		if(s == sum - s) {
    			puts("Yes");
    			return 0;
    		}
    	}
    	puts("No");
    	return 0;
    }
    

    B - MAX-=min

    题意:每次把最大值全部替换成(最大值-最小值),问最后剩下的数

    可以想到最大值为(M)最小值为(m),如果(M > 2m),那么(M)会不断变小,而(M - m <= m),最大值总在不断变小

    这其实是取余,一堆数不断互相取余最后剩下的就是这些数的最大公约数

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    
    #define pii pair<int,int>
    typedef long long int64;
    using namespace std;
    
    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 a[100005],N;
    int gcd(int a,int b) {
    	return b == 0 ? a : gcd(b, a % b);
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	read(N);
    
    	for(int i = 1 ; i <= N ; ++i) {
    		read(a[i]);
    	}
    	int t = a[1];
    	for(int i = 2 ; i <= N ; ++i) {
    		t = gcd(t,a[i]);
    	}
    	out(t);enter;
    	return 0;
    }
    

    C - Camels and Bridge

    题意:一个桥有(M)段,每个段有长度(l_{i})和容量(v_{i}),有(N)个骆驼每只体重为(w_{i}),问这些骆驼第一个到最后一个最小距离是多少

    因为(N)很小,相对顺序全排列暴力枚举,然后枚举(i,j)(i)(j)的骆驼重量总和为(V),那么容量小于(V)的桥最小距离是多少,这个可以二分和前缀取max解决

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    
    #define pii pair<int,int>
    typedef long long int64;
    using namespace std;
    
    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);
    }
    const int MAXM = 100005;
    int N,M;
    int64 w[10],l[MAXM],v[MAXM],ans,sum[10],dis[10][10],dp[10];
    int64 val[MAXM],len[MAXM];
    int a[10],id[MAXM];
    bool vis[10];
    void dfs(int d) {
    	if(d > N) {
    		for(int i = 1 ; i <= N ; ++i) {
    			sum[i] = sum[i - 1] + w[a[i]];
    		}
    		memset(dis,0,sizeof(dis));
    		for(int j = 1 ; j <= N ; ++j) {
    			for(int t = j + 1 ; t <= N ; ++t) {
    				int cv = sum[t] - sum[j - 1];
    				int p = lower_bound(val + 1,val + M + 1,cv) - val - 1;
    				if(val[p] < cv) {
    					dis[j][t] = len[p];
    				}
    			}
    		}
    		memset(dp,0,sizeof(dp));
    		for(int i = 1 ; i <= N ; ++i) {
    			for(int j = i + 1 ; j <= N ; ++j) {
    				dp[j] = max(dp[j],dp[i] + dis[i][j]);
    			}
    		}
    		ans = min(ans, dp[N]);
    		return;
    	}
    	for(int i = 1 ; i <= N ; ++i) {
    		if(!vis[i]) {
    			a[d] = i;
    			vis[i] = 1;
    			dfs(d + 1);
    			vis[i] = 0;
    		}
    	}
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	read(N);read(M);
    	for(int i = 1 ; i <= N ; ++i) read(w[i]);
    	for(int i = 1 ; i <= M ; ++i) {
    		read(l[i]);read(v[i]);
    		id[i] = i;
    		ans += l[i];
    	}
    	ans = ans * N;
    	sort(id + 1,id + M + 1,[](int a,int b) {return v[a] < v[b] || (v[a] == v[b] && l[a] > l[b]);});
    	for(int i = 1 ; i <= M ; ++i) {
    		val[i] = v[id[i]];
    		len[i] = l[id[i]];
    		len[i] = max(len[i],len[i - 1]);
    	}
    	for(int i = 1 ; i <= M ; ++i) {
    		for(int j = 1 ; j <= N ; ++j) {
    			if(w[j] > v[i]) {
    				puts("-1");
    				return 0;
    			}
    		}
    	}
    	dfs(1);
    	out(ans);enter;
    	return 0;
    }
    

    D - Let's Play Nim

    有N个包,包里有(a_i)个硬币,有(N)个盘子,第一阶段先后手轮流拿一个包,然后把包里的钱全倒在任意一个盘子里,第二阶段开始对盘子里的硬币做“一次可以取一个盘子里一个或任意多个,不能取者输的nim游戏”

    考虑第二阶段的nim,只有异或和为0这种情况后手可以赢,然而如果不是所有包可以按硬币两两配对的话,想让异或和不为0的一方总有办法让一个盘子里的东西大于(frac{sum{a_{i}}}{2})

    而这种情况下, 由于异或是按位消去,那么如果异或和为0,剩余物品的容量综合应该大于等于(frac{sum{a_{i}}}{2})于是得到矛盾

    那么想让异或和不为0的一方在不是所有包可以按硬币两两配对的情况下总可以赢,所以就直接判断第一阶段后谁先手就行了

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define MOD 998244353
    #define MAXN 100005
    typedef long long int64;
    using namespace std;
    
    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 T,N,a[MAXN];
    string nm[2] = {"First","Second"};
    void Solve() {
    	read(N);
    	for(int i = 1 ; i <= N ; ++i) {
    		read(a[i]);
    	}
    	sort(a + 1,a + N + 1);
    	int t = 0;t ^= (N & 1);
    	if(N % 2 == 0) {
    		bool f = 1;
    		for(int i = N ; i >= 1 ; i -= 2) {
    			if(a[i] != a[i - 1]) {f = 0;break;}
    		}
    		t ^= f;
    	}
    	cout << nm[t] << endl;
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	read(T);
    	while(T--) {
    		Solve();
    	}
    	return 0;
    }
    

    E - Keep Graph Disconnected

    题意:一个(N)个点的图(1)(N)不联通,先后手给图加边,要保证(1,N)不连通,不能加边者输

    如果(1)的连通块为(x),而(N)所在的连通块为(y),答案和(frac{N(N - 1)}{2} - xy - M)的奇偶性有关

    而若(N)为奇数,那么(n(N - n))一定是偶数,那么胜负固定

    如果(N)为偶数,那么如果(x,y)奇偶性不同,先手总有办法让(x,y)变成自己想要的奇偶性

    例如先手希望是偶数,就找一个奇数块连到(x,y)中为奇数的那一边

    例如先手希望是奇数,就找一个奇数块连到(x,y)是偶数的那一边

    因为总和为偶数,后手想用奇数块变(x,y)的奇偶性,先手总可以跟一步

    如果(x,y)的奇偶性相同,(xy)为奇数或者偶数

    希望是奇数/偶数的那一方,总有策略让(xy)奇偶性不变(考虑如果(xy)满足我的要求了,这一步我就把两个奇数块连成一个偶数块,若全场只剩偶数块那对方变不了我的奇偶性,若不满足我要求,我总可以拿一个奇数块变回去)

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    
    #define pii pair<int,int>
    typedef long long int64;
    using namespace std;
    
    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);
    }
    const int MAXN = 100005;
    int T,N,M;
    int a[MAXN],b[MAXN],fa[MAXN],siz[MAXN];
    string nm[2];
    int getfa(int u) {
    	return fa[u] == u ? u : fa[u] = getfa(fa[u]);
    }
    void merge(int u,int v) {
    	u = getfa(u);v = getfa(v);
    	if(u == v) return;
    	siz[u] += siz[v];
    	fa[v] = u;
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	read(T);
    	nm[1] = "First";nm[0] = "Second";
    	while(T--) {
    		read(N);read(M);
    		int u,v;
    		for(int i = 1 ; i <= N ; ++i) fa[i] = i,siz[i] = 1;
    		for(int i = 1 ; i <= M ; ++i) {
    			read(u);read(v);
    			merge(u,v);
    		}
    		int s = (1LL * N * (N - 1) / 2 - M) & 1;
    		if(N & 1) {
    			cout << nm[s] << endl;
    		}
    		else{
    			int t0 = siz[getfa(1)] & 1,t1 = siz[getfa(N)] & 1;
    			if(t0 ^ t1) {
    				cout << nm[1] << endl;
    			}
    			else {
    				cout << nm[s ^ t0] << endl;
    			}
    		}
    	}
    	return 0;
    }
    

    F - Lights Out on Connected Graph

    题意:将图(G)(M)条边任意删除或保留,这(2^{M})个生成子图中二分连通图的个数

    (注意N=1需要特判输出)

    (Nleq 17)考虑状压

    连通性考虑经典容斥:枚举1所在的连通块组成,然后乘上剩余部分的方案,是需要消去的

    首先我们考虑染色统计二分图个数(也就是一个点算成黑点和白点是两种方案),并通过容斥强行保证二分图的每个点都有连边

    (g[S])为点集S染色黑白后黑点和白点都有边连的方案数,初始化是两个点如果有边(g[S] = 2)

    然后枚举(S)的子集(T),减去(g[T] imes 2^{cnt[S oplus T]})(因为没连边的的点可能染黑或者染白)

    之后计算(f[S])为连通的染色二分图方案数,计算方法为枚举子集(T)(要保证T里有1),减去(f[T] imes g[S oplus T])

    为了消除染色的影响要除2

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define MOD 998244353
    typedef long long int64;
    using namespace std;
    
    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);
    }
    const int MAXS = (1 << 17) + 5;
    int N,M;
    int E[20],sum[MAXS],g[MAXS],f[MAXS],cnt[MAXS],pw[405];
    int lowbit(int x) {
    	return x & (-x);
    }
    int mul(int a,int b) {
    	return 1LL * a * b % MOD;
    }
    int inc(int a,int b) {
    	return a + b >= MOD ? a + b - MOD : a + b;
    }
    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;
    }
    void update(int &x,int y) {
    	x = inc(x,y);
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	read(N);read(M);
    	if(N == 1) {
    		out(1);enter;return 0;
    	}
    	int u,v;
    	for(int S = 1 ; S < (1 << N) ; ++S) cnt[S] = cnt[S - lowbit(S)] + 1;
    	for(int i = 1 ; i <= M ; ++i) {
    		read(u);read(v);
    		E[u] |= (1 << v - 1);
    		E[v] |= (1 << u - 1);
    	}
    	pw[0] = 1;
    	for(int i = 1 ; i <= M ; ++i) pw[i] = mul(pw[i - 1],2);
    	for(int S = 1 ; S < (1 << N) ; ++S) {
    		for(int i = 1 ; i <= N ; ++i) {
    			if(S >> (i - 1) & 1) {
    				sum[S] += cnt[S & E[i]];
    			}
    		}
    		sum[S] /= 2;
    	}
    	for(int S = 1 ; S < (1 << N) ; ++S) {
    		if(cnt[S] >= 2) {
    			if(cnt[S] == 2)  {
    				if(sum[S] == 1)g[S] = 2;
    			}
    			else {
    				int res = 0;
    				for(int T = (S - 1) & S; T ; T = (T - 1) & S) {
    					int num = sum[S] - sum[T] - sum[S ^ T];
    					update(res,pw[num] - 1);
    					update(res,MOD - mul(g[T],pw[cnt[S ^ T]]));
    				}
    				g[S] = res;
    			}
    		}
    	}
    	for(int S = 1 ; S < (1 << N - 1) ; ++S) {
    		int rS = S << 1 | 1;
    		f[rS] = g[rS];
    		for(int T = S ; T ; T = (T - 1) & S) {
    			int rT = T << 1 | 1;
    			int rM = (S ^ T) << 1;
    			update(f[rS],MOD - mul(f[rT],g[rM]));
    		}
    	}
    	out(mul(f[(1 << N) - 1],fpow(2,MOD - 2)));enter;
    	return 0;
    }
    
    
  • 相关阅读:
    AtCoder Regular Contest 086 E
    bzoj3192: [JLOI2013]删除物品(树状数组)
    bzoj5118: Fib数列2(费马小定理+矩阵快速幂)
    bzoj2314: 士兵的放置(树形DP)
    bzoj1907: 树的路径覆盖(树形DP)
    最小割 总结&&做题记录
    最大流 总结&&做题记录
    网络流24题之太空飞行计划
    网络流24题之负载平衡问题
    网络流24题之飞行员配对方案
  • 原文地址:https://www.cnblogs.com/ivorysi/p/13817916.html
Copyright © 2020-2023  润新知