zoukankan      html  css  js  c++  java
  • Codeforces Round #628 (Div. 2) 题解

    Codeforces Round #628 (Div. 2)

    A. EhAb AnD gCd

    题意:构造一组 ((a,b)) 满足 (GCD(a,b)+LCM(a,b)=x)

    分析(a=1,b=x-1)

    #define _CRT_SECURE_NO_WARNINGS
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma comment(linker, "/stack:200000000")
    #include <bits/stdc++.h>
    #define SIZE 200010
    #define rep(i, a, b) for (long long i = a; i <= b; ++i)
    #define mp make_pair
    #define ll long long
    using namespace std;
    void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
    ll n, t;
    
    int main() {
    	io(); cin >> t;
    	rep(ii, 1, t) {
    		cin >> n;
    		cout << 1 << ' ' << n - 1 << '
    ';
    	}
    }
    

    B. CopyCopyCopyCopyCopy

    题意:给定一个序列 (a) ,并将这个序列复制无数份接在一起,求这个无限长序列中的最长上升子序列。

    分析:由于复制了无限次,答案就是不同种类数字的数量。

    #define _CRT_SECURE_NO_WARNINGS
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma comment(linker, "/stack:200000000")
    #include <bits/stdc++.h>
    #define SIZE 1000010
    #define rep(i, a, b) for (long long i = a; i <= b; ++i)
    #define mp make_pair
    #define ll long long
    using namespace std;
    void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
    int n, t, ans;
     
    int main() {
    	io(); cin >> t;
    	rep(ii, 1, t) {
    		cin >> n;
    		vector<int> a(n);
    		rep(i, 0, (n - 1)) cin >> a[i];
    		sort(a.begin(), a.end());
    		a.erase(unique(a.begin(), a.end()), a.end());
    		cout << a.size() << '
    ';
    	}
    }
    

    C. Ehab and Path-etic MEXs

    题意:给定一棵 (n) 个点的树,你可以对树边标号为 (0,1,2,...,n-2) 。定义 (MEX(u,v)) 是说点 (u)(v) 的路径上最小的未出现的标号(例如路径上的标号是 (0,2,3) , 那结果就是 (1) ),给出一种构造方案使得对于所有 (MEX(u,v)) 的最大值最小。

    分析:如果至少有一个点的度数 (geq3) (即不为链),那么我们就能把 (0,1,2) 这三个数字分配到该点的三条邻边上,这样就能保证我任选一条路径不能同时存在这三个最小的数。

    #define _CRT_SECURE_NO_WARNINGS
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma comment(linker, "/stack:200000000")
    #include <bits/stdc++.h>
    #define SIZE 200010
    #define rep(i, a, b) for (long long i = a; i <= b; ++i)
    #define mp make_pair
    #define ll long long
    using namespace std;
    void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
    int n, t, cnt;
    int deg[SIZE];
    vector<int> vec[SIZE];
    struct Node {
    	int x, y;
    	int id;
    	int val;
    	Node() {}
    	Node(int x_, int y_) : x(x_), y(y_) {}
    	bool operator < (const Node& b) const {
    		return (x == b.x ? y < b.y : x < b.x);
    	}
    }p[SIZE];
    map<Node, int> MP;
     
    int main() {
    	io(); cin >> n;
    	rep(i, 2, n) {
    		int x, y; cin >> x >> y;
    		if (x > y) swap(x, y);
    		vec[x].emplace_back(y);
    		vec[y].emplace_back(x);
    		MP[Node(x, y)] = -1;
    		p[i - 1] = Node(x, y); p[i - 1].id = i;
    		++deg[x], ++deg[y];
    	}
    	bool f = false;
    	rep(i, 1, n) {
    		if (deg[i] > 2) {
    			for (auto it : vec[i]) {
    				int x = i, y = it;
    				if (x > y) swap(x, y);
    				MP[Node(x, y)] = cnt++;
    			}
    			break;
    		}
    	}
    	rep(i, 1, (n - 1)) {
    		if (MP[Node(p[i].x, p[i].y)] != -1) cout << MP[Node(p[i].x, p[i].y)] << '
    ';
    		else cout << cnt++ << '
    ';
    	}
    }
    

    D. Ehab the Xorcist

    题意:给定两个数字 (u)(v) ,构造一个最短的数列 (a_n) 满足 (a_1oplus a_2oplus ... oplus a_n=u) 并且 (sum^n_{i=1}a_i=v)

    分析:首先考虑不能构造的情况,容易发现 (u>v) 是不能构造的,然后根据奇偶性可以发现 (v-u) 为奇数时不能构造。在排除了本题的一些特判,比如 (u=v=0)(u=v) 之后,本题就转化为 (v-u) 为偶数时的构造问题。由于 (v-u) 为偶数,我们很快就能给出构造的上界是 (3) ,因为 (v - u) / 2 ^ (v - u) / 2 ^ u = u 。但是还要特判一下能否构造长度为 (2) 的数列,即 (v - u) / 2 ^ ((v - u) / 2 ^ u) = u

    #define _CRT_SECURE_NO_WARNINGS
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma comment(linker, "/stack:200000000")
    #include <bits/stdc++.h>
    #define SIZE 200010
    #define rep(i, a, b) for (long long i = a; i <= b; ++i)
    #define mp make_pair
    #define ll long long
    using namespace std;
    void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
    ll n, m;
    
    int main() {
    	io(); cin >> n >> m;
    	if (n > m) cout << -1;
    	else if (!n && !m) cout << 0;
    	else if (n == m) cout << 1 << '
    ' << m;
    	else {
    		if ((m - n) % 2 == 0) {
    			ll x = n, y = (m - n) / 2;
    			ll z = (x ^ y);
    			if (z + y == m) cout << "2
    " << z << ' ' << y;
    			else cout << "3
    " << x << ' ' << y << ' ' << y;
    		}
    		else cout << -1;
    	}
    }
    

    E. Ehab's REAL Number Theory Problem

    题意:给定一个数组 (a_n) ,数组中任意一个元素的因子数不超过 (7) ,找出一个最短的子序列,满足该子序列之积为完全平方数。

    分析:由于任意元素因子数不超过 (7) ,因此 (a_i) 的质因子数 (leq 2) (如果质因子数为 (3) 将有 (8) 个因子)。因此我们先将所有给定元素进行预处理,去除所有平方因子(假设一个元素为 (2^2cdot 3) 那它等价于 (3) ),然后所有元素只能是 (1,p,pq) 中的一种形式( (p,q) 为质数)。完成预处理后不难发现,如果存在 (1) ,那么结果就是最短子序列长度就是 (1) ;如果存在两个相同元素,那么结果就是 (2)

    然后,我们就可以按照处理后的元素建图了,假设一个元素是 (pq) ,那么在 (p)(q) 之间建一条边;假设一个元素是 (p) 那么在 (p)(1) 之间建边;本题的答案就是该图上的最小环,因为每个点都会被两条边连接,说明每个点被选中了偶数次。由于边权全部为 (1) ,直接跑 (bfs) 即可,但是如果对每个节点搜索,复杂度是 (O(NM)) 的,本题中我们只需要对所有权值 (leq sqrt{max {a_i}}) 的节点搜索,因为权值 (> sqrt{max {a_i}}) 的节点只可能出现 (1) 次,必定为奇数不能成环。

    #define _CRT_SECURE_NO_WARNINGS
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma comment(linker, "/stack:200000000")
    #include <bits/stdc++.h>
    #define SIZE 1000010
    #define rep(i, a, b) for (long long i = a; i <= b; ++i)
    #define mp make_pair
    #define ll long long
    using namespace std;
    void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
    int n, ans = 2e9;
    vector<int> a, fac;
    vector<int> vec[SIZE];
    int dis[SIZE];
    bool vis[SIZE];
    
    int init(int x) {
    	for (int i = 2; i * i <= x; ++i) {
    		if (x % i) continue;
    		int cnt = 0;
    		while (x % i == 0) x /= i, ++cnt;
    		if (cnt & 1) x *= i;
    	}
    	return x;
    }
    
    void bfs(int x) {
    	for (auto i : fac) dis[i] = 2e9, vis[i] = 0;
    	dis[x] = 0;
    	queue<int> q;
    	q.push(x);
    	vis[x] = true;
    	while (!q.empty()) {
    		int top = q.front();
    		q.pop();
    		vis[top] = false;
    		for (auto i : vec[top]) {
    			if (dis[i] > dis[top] + 1) {
    				dis[i] = dis[top] + 1;
    				q.push(i);
    				vis[i] = true;
    			}
    			else if (vis[i]) ans = min(ans, dis[top] + dis[i] + 1);
    		}
    	}
    }
    
    int main() {
    	io(); cin >> n;
    	a.resize(n);
    	rep(i, 0, (n - 1)) {
    		cin >> a[i];
    		a[i] = init(a[i]);
    	}
    	sort(a.begin(), a.end());
    	if (a[0] == 1) { cout << 1; return 0; }
    	a.erase(unique(a.begin(), a.end()), a.end());
    	if (a.size() < n) { cout << 2; return 0; }
    
    	for (auto i : a) {
    		vector<int> tmp(2, -1);
    		tmp[0] = i;
    		for (int j = 2; j * j <= i; ++j) {
    			if (i % j) continue;
    			tmp[0] = j;
    			i /= j;
    			if (i != 1) tmp[1] = i;
    			break;
    		}
    		if (tmp[1] == -1) tmp[1] = 1;
    		for (auto j : tmp) fac.emplace_back(j);
    		vec[tmp[0]].emplace_back(tmp[1]);
    		vec[tmp[1]].emplace_back(tmp[0]);
    	}
    	sort(fac.begin(), fac.end());
    	fac.erase(unique(fac.begin(), fac.end()), fac.end());
    	rep(i, 1, 1000) {
    		if (vec[i].empty()) continue;
    		bfs(i);
    	}
    	cout << (ans == 2e9 ? -1 : ans);
    }
    

    F. Ehab's Last Theorem

    题意:给定一个 (n) 个点 (m) 条边的无向图。要求找出一个点数恰好为 (lceil sqrt{n} ceil) 的独立集,或者找出一个点数 (geqlceil sqrt{n} ceil) 的环。

    分析:和 (CF1103C) 有异曲同工之妙,这类题型都可以通过 (dfs) 树给出构造。首先,找环是很容易的,直接在 (dfs) 树上找返祖边(回边)即可,如果存在点数 (geqlceil sqrt{n} ceil) 的环就直接输出。然后再考虑独立集的构造,我们用 (lceil sqrt{n} ceil-1) 种颜色,给 (dfs) 树上的节点按照 (dep[i]\%(lceil sqrt{n} ceil-1)) 的规则染色,由于 (dfs) 树的特性,相同深度的节点必定构成一个独立集,而在模意义下相同的任意两个不同深度节点之间,如果存在直连边就说明存在一个节点数 (geqlceil sqrt{n} ceil) 的环。因此我们只需要找到一个点数 (geqlceil sqrt{n} ceil) 的集合并恰好输出 (lceil sqrt{n} ceil) 个点。

    #define _CRT_SECURE_NO_WARNINGS
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma comment(linker, "/stack:200000000")
    #include <bits/stdc++.h>
    #define SIZE 200010
    #define rep(i, a, b) for (long long i = a; i <= b; ++i)
    #define mp make_pair
    #define ll long long
    using namespace std;
    void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
    int n, m, lim;
    int pa[SIZE], dep[SIZE], num[SIZE];
    vector<int> vec[SIZE];
    
    void dfs(int now) {
    	++num[dep[now] % (lim - 1)];
    	for (auto to : vec[now]) {
    		if (to == pa[now]) continue;
    		if (dep[to] == -1) {
    			dep[to] = dep[now] + 1;
    			pa[to] = now;
    			dfs(to);
    		}
    		else if (dep[now] - dep[to] >= lim - 1) {
    			cout << "2
    ";
    			cout << dep[now] - dep[to] + 1 << '
    ';
    			for (int i = now; i != pa[to]; i = pa[i]) cout << i << ' ';
    			exit(0);
    		}
    	}
    }
    
    int main() {
    	io(); cin >> n >> m;
    	rep(i, 0, n) dep[i] = -1;
    	dep[1] = 0;
    	lim = ceil(sqrt(1.0 * n));
    	rep(i, 1, m) {
    		int x, y; cin >> x >> y;
    		vec[x].emplace_back(y);
    		vec[y].emplace_back(x);
    	}
    	dfs(1);
    	cout << "1
    ";
    	rep(i, 0, (lim - 2)) {
    		if (num[i] < lim) continue;
    		int tot = lim;
    		rep(j, 1, n) {
    			if (dep[j] % (lim - 1) == i) {
    				if (tot-- != lim) cout << ' ';
    				cout << j;
    				if (!tot) return 0;
    			}
    		}
    	}
    }
    
  • 相关阅读:
    Android Studio插件
    android漂亮的对话框项目sweet-alert-dialog
    Android中Context详解 ---- 你所不知道的Context
    Bundle对象的使用
    Android利用Http下载文件
    文件缓存(配合JSON数组)
    android studio sqlite操作代码片段
    Android中使用ListView实现分页刷新(线程休眠模拟)(滑动加载列表)
    Android Studio 配置使用百度api (附带简单样例)
    9套Android实战经典项目资料分享给大家
  • 原文地址:https://www.cnblogs.com/st1vdy/p/12496334.html
Copyright © 2011-2022 走看看