Codeforces Round #628 (Div. 2)


傳送門

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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM