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

    A. Choose Two Numbers

    题意:让你从A集合里取一个数a,B集合里也取一个数b,使得a+b同时不存在于集合A和集合B中

    思路:直接取A和B集合中最大元素,最大元素相加必然不在A集合或者B集合里

        #include <cstdio>
        #include <algorithm>
        #include <iostream>
        #include <cstring> 
        using namespace std;
        int main()
        {
            int n, m;
            scanf("%d", &n);
            int a[n];
            for (int i = 0; i < n; i++)
                scanf("%d", &a[i]);
            scanf("%d", &m);
            int b[m];
            for (int i = 0; i < m; i++)
                scanf("%d", &b[i]);
             printf("%d %d", *max_element(a, a+n), *max_element(b, b+m));
        }
    View Code

     B.Make Product Equal One

    题意:给你一段序列,让你经过k次操作后使得这个序列积为1。

    思路:统计0的个数,统计小于等于-1的个数,之后分三种情况讨论:

    1.负数个数为偶数:直接abs(abs(a[i])-1)遍历一遍即可

    2.负数个数为奇数,且有0的存在:直接abs(abs(a[i])-1)遍历一遍即可(因为将要将其中一个-1转成1,0必然是要变成1或-1的所以不用考虑费用)

    3.负数个数为奇数数,且0不存在:abs(abs(a[i])-1)遍历一遍之后+2即可(因为将要将其中一个-1转成1

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    using namespace std;
    int main()
    {
        int n;
        scanf("%d", &n);
        int a[n];
        int cnt1 = 0, cnt0 = 0, mminus = 0x3f3f3f3f;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &a[i]);
            if (a[i] < 0)
            {
                cnt1++;
                if (abs(a[i]) < mminus)
                    mminus = a[i];
            }
            if (a[i] == 0) cnt0++;
        }
        if (cnt1 % 2 == 0)
        {
            long long ans = 0;
            for (int i = 0; i < n; i++)
                ans += abs(abs(a[i])-1);
            printf("%lld
    ", ans);
            return 0;
        }
        else
        {
            if (cnt0)
            {
                long long ans = 0;
                for (int i = 0; i < n; i++)
                    ans += abs(abs(a[i])-1);
                printf("%lld
    ", ans);
                return 0;
            }
            else
            {
                long long ans = 0;
                for (int i = 0; i < n; i++)
                    ans += abs(abs(a[i])-1);
                printf("%lld
    ", ans+2);
            return 0;
            }
        }
    }
    View Code

    C. Almost Equal

    题意:给你数字n,让你构造一个由1-2n组成的序列。序列满足每个长度为n的子序列之差不能大于1。

    思路:DFS找规律。

    规律如下:

    偶数直接输出“NO”,奇数的话就拿n=3举例。会发现1对的是2,3对的是4,5对的是6。(左边才是题目正解图)

    之后进一步观察发现1XX2XX, 14X23X,145236。奇数偶数交替填入即可。具体看代码。

    DFS找规律代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <set>
    using namespace std;
    int a[100];
    int vis[100];
    int n;
    int final_check(){
        set<int> s;
        for (int i = 1; i <= 2*n; i++){
            int sum = 0;
            for (int j = 1; j <= n; j++)
                if (i + j > 2*n) sum += a[(i+j)%(2*n)];
                else sum += a[i+j];
            s.insert(sum);
            if (s.size() > 2) return 1;
        }
        return 0;
    }
    
    int check(int cur, int goal){
        int temp = cur;
        int sum = 0;
        while (temp > cur-n) sum += a[temp--];
        return abs(sum - goal) > 1;
    }
    
    void dfs(int cur){
        if (cur == 2 * n + 1) {
            if (!final_check()){
                for (int i = 1; i <= 2*n; i++) cout << " " << a[i];
                cout << endl;
            } return ;
        }
        for (int i = 1; i <= 2*n; i++){
            if (!vis[i]){
                a[cur] = i;
                if (cur < n) vis[i] = 1, dfs(cur+1), vis[i] = 0;
                else
                {
                    int goal = 0;
                    for (int j = 1; j <= n; j++) goal += a[j];
                    if (!check(cur, goal)) vis[i] = 1, dfs(cur+1), vis[i] = 0;
                }
            }
        }
    }
    
    int main(){
        while (~scanf("%d", &n))
            dfs(1);
        return 0;
    }
    View Code

    AC代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 200000 + 100;
    int n;
    int ans[maxn];
    int main()
    {
        scanf("%d",&n);
        if (n % 2==0)
        {
            printf("NO
    ");
            return 0;
        }
        int judge = 0, cnt = 0;
        for(int i = 0; i < n; i++)
            if(judge++ % 2 == 0) ans[i] = ++cnt, ans[i+n] = ++cnt;
            else ans[i+n] = ++cnt, ans[i] = ++cnt;
        printf("YES
    ");
        for(int i = 0; i < 2 * n; i++) printf("%d ", ans[i]);
        printf("
    ");
    }
    View Code

    D.Shortest Cycle

    题意:给n个数,(a[1] - a[n]),如果如果i != j且(a[i] & a[j]) != 0,则在i与j之间建边

    求图的最小环(无向图最小环至少三个顶点)

    思路:发现题目给的n超级大,那肯定是不能暴力的。观察梯面,发现 ai  <= 1e18 ≈ 2^60。所以就想到当非零的ai数大于120(每一位有1和0两种可能,所以为 60 * 2)时最小环长度必然是3

    之后对于n <= 120时直接裸一个最小环即可。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    typedef long long ll;
    const int inf=9999999;
    using namespace std;
    const int maxm=1e5+5;
    int cnt;
    ll a[maxm];
    int d[205][205];
    int graph[205][205];
    int ans=inf;
    
    void floyd(){
        for(int k=1;k<=cnt;k++){
            for(int i=1;i<=k-1;i++)
                for(int j=i+1;j<=k-1;j++)
                    ans=min(ans,d[i][j]+graph[i][k]+graph[k][j]);
    
    
            for(int i=1;i<=cnt;i++)
                for(int j=1;j<=cnt;j++)
                    d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
        }
        if(ans==inf) puts("-1");
        else printf("%d
    ",ans);
    }
    int main(){
        int n; cin >> n;
        for (int i = 1; i <= n; i++){
            ll t; cin >> t;
            if(t) a[++cnt]=t;
        }
        if (cnt > 120){
            puts("3");
            return 0;
        }
    
        for(int i=1;i<=cnt;i++)
            for(int j=i+1;j<=cnt;j++)
                if (a[i]&a[j]) graph[i][j]=graph[j][i]=d[i][j]=d[j][i]=1;
                else graph[i][j]=graph[j][i]=d[i][j]=d[j][i]=inf;
        floyd();
        return 0;
    }
    View Code
  • 相关阅读:
    git和github的使用
    C语言 -- 链表操作
    数据结构之表达式求值(C++版)
    数据结构之一元多项式加法(C++版)
    数据结构之邻接矩阵(C++版)
    数据结构之二叉树,赫夫曼树(C++版)
    数据结构之循环队列(C++版)
    数据结构之顺序栈(C++版)
    数据结构之单链表(C++版)
    数据结构之顺序表(C++版)
  • 原文地址:https://www.cnblogs.com/Vikyanite/p/11402994.html
Copyright © 2011-2022 走看看