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 << '\n'; }
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 << '\n';
}
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 << '\n'; }
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) << '\n';
}
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 << '\n'; }
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] << '\n';
}
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,0\leq u,v\leq 10^{18}\)。
構造長度最小的數組,使得數組中所有元素的異或和為\(u\),所有元素的和為\(v\)。
思路:
- 按二進制位來考慮,令數組中一個元素為\(u\),因為這些二進制位必須有,那么\(v\geq 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 << '\n'; }
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 << '\n';
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 << '\n';
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) << '\n';
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},n\leq 10^5,a_i\leq 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 << '\n'; }
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 << '\n'; 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 << '\n'; 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 << '\n'; 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 << '\n';
}
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\)條邊的無向圖。
現在要找到:
- 剛好有\(\lceil\sqrt{n}\rceil\)個點的獨立集;
- 長度至少為\(\lceil\sqrt{n}\rceil\)的環。
找到其中一個即可。
思路:
令\(sq=\lceil\sqrt{n}\rceil\)。
- 環顯然比直接找獨立集好找,我們可以直接通過\(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 << '\n'; }
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 << '\n';
cout << dep[u] - dep[v] + 1 << '\n';
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 << '\n';
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;
}
