A. EhAb AnD gCd
签到。
Code
/*
* Author: heyuhhh
* Created Time: 2020/3/14 22:35:47
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '
'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
void run() {
int n; cin >> n;
cout << 1 << ' ' << n - 1 << '
';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
int T; cin >> T;
while(T--) run();
return 0;
}
B. CopyCopyCopyCopyCopy
因为是严格上升子序列,所以每个数至多被选择一次。
最后答案即为数组中互不重复的数字个数。
Code
/*
* Author: heyuhhh
* Created Time: 2020/3/14 22:43:53
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '
'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
void run() {
int n; cin >> n;
vector <int> a(n);
for(int i = 0; i < n; i++) cin >> a[i];
sort(all(a));
a.erase(unique(all(a)), a.end());
cout << sz(a) << '
';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
int T; cin >> T;
while(T--) run();
return 0;
}
C. Ehab and Path-etic MEXs
贪心。从叶子结点开始放置即可。
Code
/*
* Author: heyuhhh
* Created Time: 2020/3/14 22:50:27
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '
'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
int n;
vector <int> G[N];
int ans[N];
void run() {
cin >> n;
for(int i = 1; i < n; i++) {
int u, v; cin >> u >> v;
G[u].push_back(i);
G[v].push_back(i);
}
memset(ans, -1, sizeof(ans));
int now = 0;
for(int i = 1; i <= n; i++) if(sz(G[i]) == 1){
for(auto it : G[i]) if(ans[it] == -1) ans[it] = now++;
}
for(int i = 1; i < n; i++) if(ans[i] == -1) ans[i] = now++;
for(int i = 1; i < n; i++) cout << ans[i] << '
';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
D. Ehab the Xorcist
题意:
给出两个数(u,v,0leq u,vleq 10^{18})。
构造长度最小的数组,使得数组中所有元素的异或和为(u),所有元素的和为(v)。
思路:
- 按二进制位来考虑,令数组中一个元素为(u),因为这些二进制位必须有,那么(vgeq u)才合法。
- 令(d=v-u),考虑(d)的二进制位。若干(d)在第(k)位为(1),那么我们可以将其加在这一位上,或者加两倍在第(k-1)位上。因为要满足异或关系,所以不能改变二进制位的奇偶性,所以我们选择加两倍在(k-1)位上。若不能加则不合法。
- 那么现在得到了(cnt[i])表示第(i)个二进制位为几倍,那么最终数组个数即为(max{cnt_i})。贪心得到数组元素即可。
代码如下:
Code
/*
* Author: heyuhhh
* Created Time: 2020/3/14 23:13:48
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '
'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 64;
int cnt[N], need[N];
void run() {
ll u, v; cin >> u >> v;
for(int i = 0; i < N; i++) if(u >> i & 1) ++cnt[i];
if(u > v) {
cout << -1 << '
';
return;
}
ll d = v - u;
for(int i = N - 1; i >= 0; i--) if(d >> i & 1) {
if(i) cnt[i - 1] += 2;
else {
cout << -1 << '
';
return;
}
}
vector <ll> ans;
while(1) {
bool ok = false;
for(int i = 0; i < N; i++) if(cnt[i]) ok = true;
if(!ok) break;
ll res = 0;
for(int i = 0; i < N; i++) if(cnt[i]) {
res += 1ll << i;
--cnt[i];
}
ans.push_back(res);
}
cout << sz(ans) << '
';
for(auto it : ans) cout << it << ' ';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
E. Ehab's REAL Number Theory Problem
题意:
给出(a_{1,2,...,n},nleq 10^5,a_ileq 10^6),保证每个元素至多(7)个因子。
现在要从序列中选择长度最少的数,使得其乘积为完全平方数。
思路:
- 由每个元素至多(7)个因子我们可以知道每个元素至多两个素因子,并且有如下几种形式:(p,p^2,pq,p^2q)。
- 乘积为完全平方数则等价于乘积的素因子指数都为偶数。据此显然(p^2q)与(q)这种形式等价。
- 对于(p^2)这种形式,我们可以直接单独考虑,那么最后就只剩下(p,pq)这两种形式。我们现在要选取最少的数,使得其乘积为完全平方数。也就是最后每个质因子的指数为(2)。
- 我们将(p)抽象为((1,p),pq)抽象为((p,q))。那么问题等价于求一个长度最小的环。因为环中每个点的度数为(2),也就是每个质因子的指数为(2)。
- 直接通过(dfs)树或者(bfs)树来求解的话时间复杂度为(O(n^2))。注意到一个环中最多只有(1)个数大于(1000),那么我们枚举所有不超过(1000)的数找环即可。
一点题外话:
最终通过(dfs)树或者(bfs)树来找环感觉有点迷。因为从一个点出发不能找出所有的环。(bfs)树还好,能找到起点所在的所有环;(dfs)树应该是找到所有依附于(dfs)树上的边的所有环,这样的话(dfs)的顺序不同找到的环也可能不同,感觉可能就存在随机性?
但代码我是直接(dfs)的,也通过了所有样例。
如果有大佬知道其中的一些原理,希望能不吝赐教。
Code
/*
* Author: heyuhhh
* Created Time: 2020/3/15 11:47:16
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '
'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e6 + 5;
int n;
int a[N];
int vis1[N];
map <pii, int> vis2;
vector <int> v[N];
int mp[N], tot;
int dep[N];
vector <int> G[N];
int ans;
void dfs(int u, int fa) {
dep[u] = dep[fa] + 1;
for(auto v : G[u]) if(v != fa) {
if(dep[v] == 0) dfs(v, u);
else if(dep[u] > dep[v]) {
ans = min(ans, dep[u] - dep[v] + 1);
}
}
}
void run() {
cin >> n;
bool ok = false;
for(int i = 1; i <= n; i++) {
cin >> a[i];
if(a[i] == 1) ok = true;
int t = a[i], num = 0;
for(int x = 2; 1ll * x * x <= a[i]; x++) {
if(a[i] % x == 0) {
int cnt = 0;
while(a[i] % x == 0) a[i] /= x, ++cnt;
if(cnt & 1) v[i].push_back(x);
else ++num;
}
}
if(a[i] > 1) v[i].push_back(a[i]);
if(num && !sz(v[i])) ok = true;
a[i] = t;
}
if(ok) {
cout << 1 << '
'; return;
}
for(int i = 1; i <= n; i++) {
if(sz(v[i]) == 1) {
int from = 1, to = v[i][0];
if(!mp[from]) mp[from] = ++tot;
if(!mp[to]) mp[to] = ++tot;
G[mp[from]].push_back(mp[to]);
G[mp[to]].push_back(mp[from]);
if(++vis1[v[i][0]] > 1) {
cout << 2 << '
'; return;
}
}
if(sz(v[i]) == 2) {
int from = v[i][0], to = v[i][1];
if(!mp[from]) mp[from] = ++tot;
if(!mp[to]) mp[to] = ++tot;
G[mp[from]].push_back(mp[to]);
G[mp[to]].push_back(mp[from]);
if(++vis2[MP(from, to)] > 1) {
cout << 2 << '
'; return;
}
}
}
ans = INF;
for(int i = 1; i <= 1000; i++) if(mp[i]) {
for(int j = 1; j <= tot; j++) dep[j] = 0;
dfs(mp[i], 0);
}
if(ans == INF) ans = -1;
cout << ans << '
';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
F. Ehab's Last Theorem
题意:
给出(n)个点,(m)条边的无向图。
现在要找到:
- 刚好有(lceilsqrt{n} ceil)个点的独立集;
- 长度至少为(lceilsqrt{n} ceil)的环。
找到其中一个即可。
思路:
令(sq=lceilsqrt{n}
ceil)。
- 环显然比直接找独立集好找,我们可以直接通过(dfs)树来找环。
- 构建出(dfs)树后,若找不到长度不小于(sq)的环。我们将结点深度按照(\%(sq-1))进行分类。因为不存在环,那么显然现在任意同类的结点直接不会存在边。
- 根据抽屉原理,必然会存在一类,其结点个数不小于(sq)。那么直接贪心找即可。
这个题也很巧妙,主要是(dfs)树的运用。题解中提到了一篇博客,写得挺细致的:传送门
代码如下:
Code
/*
* Author: heyuhhh
* Created Time: 2020/3/15 10:36:27
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '
'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
int n, m, sq;
vector <int> G[N];
int dep[N];
vector <int> cyc;
void dfs(int u) {
cyc.push_back(u);
dep[u] = sz(cyc) - 1;
for(auto v : G[u]) {
if(dep[v] != -1) {
if(dep[u] - dep[v] + 1 >= sq) {
cout << 2 << '
';
cout << dep[u] - dep[v] + 1 << '
';
while(1) {
int now = cyc.back();
cout << now << ' ';
if(now == v) break;
cyc.pop_back();
}
exit(0);
}
} else dfs(v);
}
cyc.pop_back();
}
int cnt[N];
void run() {
memset(dep, -1, sizeof(dep));
cin >> n >> m;
for(int i = 1; i <= m; i++) {
int u, v; cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
sq = 1;
while(1ll * sq * sq < n) ++sq;
dfs(1);
for(int i = 1; i <= n; i++) ++cnt[dep[i] % (sq - 1)];
int Max = *max_element(cnt, cnt + n + 1);
cout << 1 << '
';
vector <int> ans;
for(int i = 1; i <= n; i++) if(cnt[dep[i] % (sq - 1)] == Max) ans.push_back(i);
ans.resize(sq);
for(auto it : ans) cout << it << ' ';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}