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

    A

    输出 (1,n-1)

    #include <bits/stdc++.h>
    using namespace std;
    
    signed main() {
        int t,a,b;
        cin>>t;
        while(t--) {
            cin>>a;
            cout<<1<<" "<<a-1<<endl;
        }
    }
    
    

    B

    不同数字个数

    #include <bits/stdc++.h>
    using namespace std;
    
    set<int> s;
    int t,n,a[100005];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>t;
        while(t--) {
            cin>>n;
            for(int i=1;i<=n;i++) {
                cin>>a[i];
                if(s.find(a[i])==s.end()) s.insert(a[i]);
            }
            cout<<s.size()<<endl;
            s.clear();
        }
    }
    
    

    C

    给树上所有边分配边权 (0,1,...,n-2),要求任意两点的路径上的 MEX 的最大值最小

    如果树是一条链,答案为 (n-1),边权随便设

    如果树不是链,答案为 (2),找到一个度数大于 (2) 的点,找到它的任意三条边,令其为 (0,1,2),其它的随便设

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 200005;
    int n,u,v,d[N],a[N];
    vector <int> id[N];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<n;i++) {
            cin>>u>>v;
            d[u]++;
            d[v]++;
            id[u].push_back(i);
            id[v].push_back(i);
        }
        int p=max_element(d+1,d+n+1)-d;
        if(d[p]<=2) {
            for(int i=1;i<n;i++) cout<<i-1<<endl;
        }
        else {
            a[id[p][0]]=1;
            a[id[p][1]]=2;
            a[id[p][2]]=3;
            int ind=3;
            for(int i=1;i<n;i++) if(a[i]==0) a[i]=++ind;
            for(int i=1;i<n;i++) cout<<a[i]-1<<endl;
        }
    }
    
    

    D

    给定 (u,v leq 10^{18}),求长度最短的数组,使得异或和为 (u),代数和为 (v)

    如果 (u,v) 奇偶性不同,或 (u>v),则一定不合法

    所以 (v-u) 一定是偶数,直观地,我们可以用 (u,(v-u)/2,(v-u)/2) 来表示,但这当中有一些是非最优的,也有一些是非法的

    当且仅当 (u=v=0),输出一个空数组即可

    当且仅当 (u=v),上述表示非法,而此时只需要这个数本身就可以了,(n=1)

    考虑何时 (n=2)

    显然 (u=0) 时可以

    另一种情况是, ((v+u)/2, (v-u)/2) 的异或值等于 (u)

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    int u,v;
    
    signed main() {
        cin>>u>>v;
        if((u-v)%2 || u>v) cout<<-1;
        else if(u==0&&v==0) cout<<0;
        else if(u==v) cout<<1<<endl<<u;
        else if(u==0) cout<<2<<endl<<v/2<<" "<<v/2;
        else if((((v+u)/2)^((v-u)/2))==u) cout<<2<<endl<<(v+u)/2<<" "<<(v-u)/2;
        else cout<<3<<endl<<u<<" "<<(v-u)/2<<" "<<(v-u)/2;
    }
    
    

    E

    给一些数,每个数的因数个数不超过 (7),求最少选出多少个使得乘积为完全平方数

    由于每个数的因数个数不超过 (7),每个数的质因子个数一定 (leq 2)

    那么一个很直观的想法是,对于质因子个数为 (2) 的数,我们可以将质因子设为结点,那么这些数就是边

    如果一个数的质因子只有一个(如果有两个质因子且某个质因子的幂指数是 (2) 我们就当做 (0) 处理),则额外构建一个 (1) 结点,将这个质因子与 (1) 连边来表示这个数

    如果一个数只有一个质因子并且幂指数为 (2),就当做自环,或者这时直接输出 (1) 然后结束

    经过这样的建图后,找这个图中的最小环就是答案

    发现环内必有一个点 (leq sqrt{max a_i})

    于是只从这些数开始暴力 BFS 即可

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1000005;
    const int MAXN = 1000005;
    int prime[MAXN+1];
    void presolve() {
        memset(prime,0,sizeof prime);
        for(int i=2;i<=MAXN;i++) {
            if(!prime[i]) prime[++prime[0]]=i;
            for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++) {
                prime[prime[j]*i]=1;
                if(i%prime[j]==0) break;
            }
        }
    }
    
    int n,ans=1e9,dis[N],vis[N];
    vector <int> g[N];
    
    void make(int p,int q) { //cout<<p<<","<<q<<endl;
        g[p].push_back(q);
        g[q].push_back(p);
    }
    
    void solve(int i) {
        queue <pair<int,int> > q;
        q.push({i,0});
        memset(dis,0x3f,sizeof dis);
        memset(vis,0x00,sizeof vis);
        dis[i]=0;
        while(q.size()) {
            int p=q.front().first, fa=q.front().second; q.pop();
            for(int x:g[p]) if(x!=fa) {
                if(dis[x]>1e9) {
                    dis[x]=dis[p]+1;
                    if(!vis[x]) {
                        vis[x]=1;
                        q.push({x,p});
                    }
                }
                else {
                    ans=min(ans,dis[x]+dis[p]+1);
                }
            }
        }
    }
    
    signed main() {
        presolve();
        cin>>n;
        while(n--) {
            int x;
            cin>>x;
            vector <int> vec;
            int t=x;
            for(int i=1;prime[i]*prime[i]<=x&&t>1;i++) {
                if(t%prime[i]==0) {
                    int tmp=0;
                    while(t%prime[i]==0) t/=prime[i], tmp^=1;
                    if(tmp) vec.push_back(prime[i]);
                }
            }
            vec.push_back(t);
            if(vec.size()==0) {
                cout<<1;
                return 0;
            }
            if(vec.size()==1) {
                vec.push_back(1);
            }
            make(vec[0],vec[1]);
        }
        for(int i=1;i<=1000;i++) solve(i);
        if(ans>=1e9) cout<<-1;
        else cout<<ans;
    }
    

    F

    给定无向图,找出至少有 (lceil sqrt n ceil) 个点的环,或者正好有 (lceil sqrt n ceil) 个点的独立集

    建立一棵 DFS 树,枚举所有非树边,如果找到某个非树边连接的两个点深度之差 (geq [sqrt n]-1),则输出之

    否则一定有符合条件的独立集,于是我们仍然把图 DFS 一遍,对于一个点,能选就选,并将相邻所有点打标记即可

    注意打标记是在处理完这个点的所有相邻点之后,方可保证最优(这个地方感觉很诡异,最后一分钟瞎改改过的)

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 500005;
    
    int n,m,t1,t2,t3,lim;
    int dep[N],vis[N],fg[N];
    vector <int> g[N];
    vector <int> sta;
    
    void dfs1(int p) {
        sta.push_back(p);
        vis[p]=1;
        for(int q:g[p]) {
            if(!vis[q]) {
                dep[q]=dep[p]+1;
                dfs1(q);
            }
            else {
                if(dep[q] && dep[p]-dep[q]>=lim-1) {
                    cout<<2<<endl<<dep[p]-dep[q]+1<<endl;
                    while(sta.back()!=q && sta.size()) {
                        cout<<sta.back()<<" ";
                        sta.pop_back();
                    }
                    cout<<q<<endl;
                    exit(0);
                }
            }
        }
        sta.pop_back();
    }
    
    void dfs2(int p) {
        vis[p]=1;
        for(int q:g[p])
            if(!vis[q]) dfs2(q);
    
        for(int q:g[p]) if(!fg[p]) fg[q]=1;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        lim=1;
        while(lim*lim<n) ++lim;
        for(int i=1;i<=m;i++) {
            cin>>t1>>t2;
            g[t1].push_back(t2);
            g[t2].push_back(t1);
        }
        dep[1]=1;
        dfs1(1);
        memset(vis,0,sizeof vis);
        dfs2(1);
        int cnt=lim;
        cout<<1<<endl;
        for(int i=1;i<=n && cnt;i++) {
            if(!fg[i]) cout<<i<<" ", --cnt;
        }
    }
    
    
  • 相关阅读:
    数据库——表操作(5)
    数据库——存储引擎(4)
    数据库——库操作(3)
    数据库——初始mysql语句(2)
    数据库——初识数据库(1)
    并发编程——协程(5)
    并发编程——IO模型(6)
    并发编程——多线程(4)
    并发编程——多进程——multiprocessing开启进程的方式及其属性(3)
    并发编程——多进程——理论(2)
  • 原文地址:https://www.cnblogs.com/mollnn/p/12521351.html
Copyright © 2011-2022 走看看