• Codeforces Round #572 (Div. 2)


    Contest Info


    [Practice Link](https://codeforc.es/contest/1189)
    Solved A B C D1 D2 E F
    6/7 Ø Ø Ø Ø Ø Ø -
    • O 在比赛中通过
    • Ø 赛后通过
    • ! 尝试了但是失败了
    • - 没有尝试

    Solutions


    A. Keanu Reeves

    签到题。

    #include <bits/stdc++.h>
    using namespace std;
     
    #define N 1100
    char s[N]; int n;
     
    int main() {
    	while (scanf("%d%s", &n, s + 1) != EOF) {
    		int cnt = 0;
    		for (int i = 1; i <= n; ++i) {
    			if (s[i] == '1') ++cnt;
    			else --cnt;
    		}  
    		if (cnt) {
    			puts("1"); puts(s + 1);
    		} else {
    			puts("2");
    			printf("%c %s
    ", s[1], s + 2);
    		}
    	}
    	return 0;
    }
    

    B. Number Circle

    题意:
    有一个序列(a_1, a_2, cdots, a_n),要求重新排列构成一个环,任意一个数都要满足严格小于旁边两数之和。
    输出方案;

    思路:
    本来的想法是最大的放中间,次大,第三大的放旁边这样一次放下去,但是发现这样并不总能构造出解。
    后来想想,直接降序排,那么其中除了最大的一个元素可能不满足,其他元素肯定都满足。
    那么我们先降序排,有(a_n, a_{n - 1}, cdots, a_1)
    然后将(a_{n - 1})移到最后一个,依然满足其他元素都满足,最大的那个元素可能不满足。
    但是这个情况下,如果最大的元素都不满足,那肯定满足不了了,因为和最大的元素相邻的是次大的和第三大的。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
     
    #define N 100010
    int n, a[N], b[N];
     
    bool ok(int *a) {
    	if (a[2] + a[n] <= a[1]) return 0;
    	if (a[1] + a[n - 1] <= a[n]) return 0;
    	for (int i = 2; i < n; ++i) {
    		if (a[i - 1] + a[i + 1] <= a[i]) {
    			return 0;
    		}
    	}
    	return 1;
    }
     
    int main() {
    	while (scanf("%d", &n) != EOF) {
    		for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    		sort(a + 1, a + 1 + n, [](int x, int y) {
    			return x > y;		
    		});
    		b[1] = a[1];
    		for (int i = 3; i <= n; ++i) b[i - 1] = a[i];
    		b[n] = a[2];
    		if (ok(b)) {
    			puts("YES");
    			for (int i = 1; i <= n; ++i) printf("%d%c", b[i], " 
    "[i == n]);
    		} else {
    			puts("NO");
    		}
    	}
    	return 0;
    }
    

    C. Candies!

    题意:
    (n)个数(s_i(0 leq s_i leq 9)),定义这样一种过程:

    • 对于长度为(2)的幂次的子区间([a_1, a_2, cdots, a_{2^k}]),每次替换((a_{2i}, a_{2i + 1})(0 leq i < 2^{k -1}))((a_{2i} + a_{2i + 1}) mod 10)
    • 如果某一步的(a_{2i} + a_{2i + 1} >= 10),那么会获得一个糖果
    • 重复操作,知道序列中数的个数变为(1)
      每次询问(f[a_1, a_2, cdots, a_{2^k}])表示([a_1, a_2, cdots, a_{2^k}])这个区间执行上述操作最后得到的糖果个数是多少。

    思路:
    (f[i][j])表示以第(i)位为起点,长度为(j)的区间的糖果个数多少,倍增即可。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
     
    #define N 100010
    #define D 20
    int n, q, l, r, a[N];
    int f[N][20], g[N][20];
     
    int main() {
    	while (scanf("%d", &n) != EOF) {
    		memset(f, 0, sizeof f);
    		memset(g, 0, sizeof g);
    		for (int i = 1; i <= n; ++i) scanf("%d", a + i), g[i][0] = a[i]; 
    		for (int j = 1; j <= 20; ++j) {
    			for (int i = 1; i <= n; ++i) {
    				if (i + (1 << j) - 1 > n) break;
    				int nx = (i + (1 << (j - 1)));
    				f[i][j] = f[i][j - 1] + f[nx][j - 1];
    				g[i][j] = g[i][j - 1] + g[nx][j - 1];
    				if (g[i][j] >= 10) {
    					++f[i][j];
    					g[i][j] %= 10;
    				}
    			}
    		}
    		scanf("%d", &q);
    		while (q--) {
    			scanf("%d%d", &l, &r);
    			int t = r - l + 1, q = 0;
    			while (t) {
    				++q;
    				t /= 2;
    			}
    			--q;
    			printf("%d
    ", f[l][q]);
    		}
    	}
    	return 0;
    }
    

    D1. Add on a Tree

    题意:
    有一棵树,每次可以选取两个叶子结点,将这两个叶子的简单路径上的所有边的边全加上(x)
    询问给定任意一种边权方案,是否都能通过有限次这种操作完成。

    思路:
    当且仅当树中没有度数为(2)的点的时候,可以。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
     
    #define N 100010
    int n, a[N], d[N];
     
    int main() {
    	while (scanf("%d", &n) != EOF) {
    		memset(d, 0, sizeof d);
    		for (int i = 1, u, v; i < n; ++i) {
    			scanf("%d%d", &u, &v);
    			++d[u]; ++d[v];
    		}
    		bool F = 1;
    		for (int i = 1; i <= n; ++i) if (d[i] == 2) F = 0;
    		puts(F ? "YES" : "NO");
    	}
    	return 0;
    }
    

    D2. Add on a Tree: Revolution

    题意:
    和D1的不同之处在于每次加的(x)都是整数,而且这次给出边的需求边权,要求一种方案。并且边权都是偶数。

    思路:
    当且仅当树中没有度数为(2)的点的时候, 为什么?
    首先,除了叶子结点意外以外,其他结点的度数都(>= 3)。 那么我们考虑其中一个点(u),有三个点(l_1, l_2, v)分别属于(u)的三个不同子树。
    那么我们要想改变((u, v))这条边的边权为(x),那么我们这么操作:

    • ((g[v], g[l_1]))(frac{x}{2})
    • ((g[v], g[l_2]))(frac{x}{2})
    • ((g[l_1], g[l_2]))(-frac{x}{2})

    其中(g[u])表示的是(u)子树下的某个叶子结点。
    这样之后我们发现我们将((g[l_1], g[l_2]))上的边的边权恢复原状了。
    而只改动了((u, g[v]))路径上的边,并且((u, v))这条边已经达到要求了。
    ((v, g[v]))这些边直接更改他们的需求,递归下去做即可。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    #define N 1100
    int n, leaf[N], W[N], g[N], root;   
    int e[N][3];
    vector <vector<int>> G;
    struct node {
    	int u, v, w;
    	node() {}
    	node(int u, int v, int w) : u(u), v(v), w(w) {}
    };
    vector <node> res; 
    
    bool ok() {
    	for (int i = 1; i <= n; ++i) {
    		if (G[i].size() == 2) {
    			return 0;
    		}
    		if (root == -1 || G[i].size() > G[root].size()) {
    			root = i;
    		}
    	}	
    	return 1;
    }
    
    int getleaf(int u) {
    	if (G[u].size() == 0) return u;
    	for (auto v : G[u]) {
    		return getleaf(v); 
    	}
    }
    
    int fa[N];
    void pre(int u) {
    	for (auto v : G[u]) if (v != fa[u]) {
    		fa[v] = u;
    		pre(v);
    	}
    }
    
    void DFS(int u) {
    	if (G[u].empty()) return;
    	for (auto v : G[u]) leaf[v] = getleaf(v); 
    	int sze = (int)G[u].size();
    	if (sze >= 2) {
    		g[G[u][0]] = leaf[G[u][1]];  
    	}
    	for (int i = 1; i < sze; ++i) {
    		g[G[u][i]] = leaf[G[u][i - 1]];
    	}
    	for (int sze = (int)G[u].size(), i = 0; i < sze; ++i) {
    		int v = G[u][i];
    	    int nx, nnx;
    		if (u == root) {
    			if (i == 0) {
    				nx = leaf[G[u][1]], nnx = leaf[G[u][2]];
    			} else if (i == sze - 1) {
    				nx = leaf[G[u][i - 1]], nnx = leaf[G[u][i - 2]];	
    			} else {
    				nx = leaf[G[u][i - 1]], nnx = leaf[G[u][i + 1]];
    			}
    		} else {
    			nx = g[u];
    			if (i == 0) {
    				nnx = leaf[G[u][1]];
    			} else {
    				nnx = leaf[G[u][i - 1]];
    			}
    		}	
    		res.push_back(node(leaf[v], nx, W[v] / 2));
    		res.push_back(node(leaf[v], nnx, W[v] / 2));
    		res.push_back(node(nx, nnx, -W[v] / 2));
    		//cout << v << " " << nx << " " << nnx << endl;
    		int it = leaf[v];
    		while (it != v) {
    			W[it] -= W[v];
    			it = fa[it];
    		}
    	}
    	for (auto v : G[u]) DFS(v);
    }
    	
    int main() {
    	while (scanf("%d", &n) != EOF) {
    		G.clear(); G.resize(n + 1); 
    		for (int i = 1; i < n; ++i) {
    			int &u = e[i][0], &v = e[i][1], &w = e[i][2];
    			scanf("%d%d%d", &u, &v, &w);
    			G[u].push_back(v);
    			G[v].push_back(u);
    		}
    		root = -1;
    		if (!ok()) {
    			puts("NO");
    		} else {
    			if (n == 2) {
    				printf("YES
    1
    ");
    				printf("1 2 %d
    ", e[1][2]);
    				continue;
    			}
    			res.clear();
    			pre(root);
    			G.clear(); G.resize(n + 1);
    			for (int i = 1; i < n; ++i) {
    				if (fa[e[i][0]] == e[i][1]) {
    					swap(e[i][0], e[i][1]);
    				}
    				G[e[i][0]].push_back(e[i][1]);
    				W[e[i][1]] = e[i][2];
    			}
    			DFS(root); 
    			puts("YES");
    			printf("%d
    ", (int)res.size());
    			assert(res.size() <= 100000);
    			for (auto it : res) {
    				printf("%d %d %d
    ", it.u, it.v, it.w);
    			}
    		}
    	}
    	return 0;
    }
    

    E. Count Pairs

    题意:
    给出(n)个数(a_i),询问有多少对((i, j))满足((a_i + a_j)(a_i^2 + a_j^2) equiv k mod p)

    思路:

    [egin{eqnarray*} (a_i + a_j)(a_i^2 + a_j^2) &equiv& k mod p ightarrow \ (a_i + a_j)(a_i - a_j)(a_i^2 + a_j^2) &equiv& k(a_i - a_j) mod p ightarrow \ (a_i^4 - a_j^4) &equiv& k(a_i - a_j) mod p ightarrow \ (a_i^4 - ka_i) - (a_j^4 - ka_j) &equiv& 0 mod p ightarrow \ a_i^4 - ka_i &equiv& a_j^4 - ka_j mod p end{eqnarray*} ]

    然后直接统计即可。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
     
    #define N 300010
    #define ll long long
    int n; ll p, k, a[N];
    map <ll, int> mp;
     
    int main() {
    	while (scanf("%d%lld%lld", &n, &p, &k) != EOF) {
    		for (int i = 1; i <= n; ++i) {
    			scanf("%lld", a + i);
    			a[i] = (a[i] * a[i] % p * a[i] % p - k + p) % p * a[i] % p;
    		}
    		sort(a + 1, a + 1 + n);
    		mp.clear();
    		ll res = 0;
    		for (int i = 1; i <= n; ++i) {
    			if (mp.find(a[i]) != mp.end()) {
    				res += mp[a[i]]; 
    			}
    		//	if (mp.find(p - a[i]) != mp.end()) {
    		//		res += mp[p - a[i]];
    		//	}
    			mp[a[i]]++;
    		}
    		printf("%lld
    ", res);
    	}
    	return 0;
    }
    
  • 相关阅读:
    用 ArcMap 发布 ArcGIS Server FeatureServer Feature Access 服务 PostgreSQL 版本
    ArcMap 发布 ArcGIS Server OGC(WMSServer,MapServer)服务
    ArcScene 创建三维模型数据
    ArcMap 导入自定义样式Symbols
    ArcMap 导入 CGCS2000 线段数据
    ArcMap 导入 CGCS2000 点坐标数据
    ArcGis Server manager 忘记用户名和密码
    The view or its master was not found or no view engine supports the searched locations
    python小记(3)操作文件
    pytest(2) pytest与unittest的区别
  • 原文地址:https://www.cnblogs.com/Dup4/p/11144057.html
Copyright © 2020-2023  润新知