• 6月10日省中提高组题解


    【题目链接】

              点击打开链接

    Problem A group

         我们发现,如果存在三个人互相不认识的情况,则输出“no”,否则输出“yes”

    【代码】

               

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 110
    
    int i,j,k,n,u;
    bool g[MAXN][MAXN];
    bool flag;
    
    template <typename T> inline void read(T &x)
    {
        int f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    template <typename T> inline void write(T x)
    {
        if (x < 0)
        {
            putchar('-');
            x = -x;
        }
        if (x > 9) write(x/10);
        putchar(x%10+'0');
    }
    template <typename T> inline void writeln(T x)
    {
        write(x);
        puts("");
    }
    
    int main() {
            
            while (scanf("%d",&n) != EOF)
            {
                    flag = false;
                    memset(g,false,sizeof(g));
                    for (i = 1; i <= n; i++)
                    {
                            while (scanf("%d",&u) && u) g[i][u] = true;
                    }
                    for (i = 1; i <= n; i++)
                    {
                            for (j = 1; j <= n; j++)
                            {
                                    for (k = 1; k <= n; k++)
                                    {
                                            if (i == j || i == k || k == j) continue;
                                            if ((!g[i][j] || !g[j][i]) && (!g[i][k] || !g[k][i]) && (!g[k][j] || !g[j][k]))
                                                    flag = true;
                                    }                
                            }
                    }
                    if (flag) printf("NO
    ");
                    else printf("YES
    ");
            }
            
            return 0;
        
    }

    Problem B flyer

          Part A : 部分分算法

          1.1 对于30%的数据,Max(Ci)≤10000,N≤1000,那么,暴力模拟即可

          1.2  20%数据满足Ai=Ci,那么,只需用stl库里的map统计答案,即可

          1.3  综合前两种部分分算法,期望得分 : 50

          1.4  根据异或运算的性质,我们知道两个相同的数异或会抵消,那么我们只需每次枚举那些位置获得了物品,将这些位置

                 异或,最后,如果异或后的值为0,则无解,否则有解,统计获得了多少物品我们依然用stl库里的map计算,期望得分                  :70

          Part B : 满分算法:

           利用题目中的条件,最多只有一个人获得奇数个物品,那么如果在区间[1,2^32]每个人获得物品的累加和为奇数,则有                 解,否则无解

           那么,我们考虑 : 对于区间[l,r],我们将它分成[l,mid]和[mid+1,r],如果区间[l,r]每个人获得物品累加和为奇数,则说明

           答案在这个区间,否则,答案在区间[mid+1,r]中,那么,我们就可以通过这种二分的方式,求出要求的位置,时间复杂度 :

           O(Nlog(N))

          【代码】

                    

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 20010
    
    int i,n;
    long long mx,l,r,mid;
    long long a[MAXN],b[MAXN],c[MAXN];
    
    inline long long calc(long long l,long long r)
    {
            int i;
            long long k,ans = 0,L,R;
            for (i = 1; i <= n; i++)
            {
                    if (a[i] > r || c[i] < l) continue;    
                    if (l >= a[i]) 
                    {
                            if ((l - a[i]) % b[i] == 0) k = (l - a[i]) / b[i];
                            else k = (l - a[i]) / b[i] + 1;
                    } else k = 0;
                    L = a[i] + k * b[i];
                    R = min(r,c[i]);
                    if (L > R) continue;
                    ans += (R - L) / b[i] + 1;
            }        
            return ans;
    }
    
    int main() 
    {
            
            mx = 1;
            for (i = 1; i <= 32; i++) mx *= 2;
            while (scanf("%d",&n) != EOF)
            {
                    for (i = 1; i <= n; i++) scanf("%lld%lld%lld",&a[i],&c[i],&b[i]);
                    if (calc(1,mx) % 2 == 0) printf("DC Qiang is unhappy.
    ");
                    else 
                    {
                            l = 1; r = mx;
                            while (l <= r)
                            {
                                    mid = (l + r) >> 1;
                                    if (calc(l,mid) % 2 == 1) r = mid - 1;
                                    else l = mid + 1;
                            }
                            printf("%lld %lld
    ",l,calc(l,l));
                    }
            }
            
            return 0;
        
    }

    Problem C Weight 

            Part A : 部分分算法

            1.1 对于每次询问DFS,期望得分 : 30

            1.2 先处理所有可以称出的物品的重量,将它放入一张哈希表中,每次询问只需查询哈希表中有没有这个数,时间复杂度

                   大约是O(3^n),期望得分 : 70

            Part B : 满分算法

            算法1.2起到了引导思考的作用,我们发现如果按1.2做,时间复杂度最劣时达到O(3^24)

            考虑使用折半搜索(中途相遇法),将每次询问的数 a 分成 x + y,x在前半部分中,y在后半部分中,那么,我们只需

            先求出前半和后半部分能称出物品的重量,每次询问,在前一半数中找到x,如果后一半数中有a - x这个数,输出yes,否则

            输出no,显然可以二分,时间复杂度 : O(3^(N/2)+Mlog(3^(N/2)))

           【代码】

                     

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 25
    
    int i,j,n,m,len;
    long long w,t;
    long long a[MAXN];
    vector<long long> x,y;
    bool flag;
    
    template <typename T> inline void read(T &x)
    {
        int f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    template <typename T> inline void write(T x)
    {
        if (x < 0)
        {
            putchar('-');
            x = -x;
        }
        if (x > 9) write(x/10);
        putchar(x%10+'0');
    }
    template <typename T> inline void writeln(T x)
    {
        write(x);
        puts("");
    }
    inline bool search(long long x)
    {
            int l = 0,r = y.size() - 1,mid;
            while (l <= r)
            {
                    mid = (l + r) >> 1;
                    if (y[mid] == x) return true;
                    if (x < y[mid]) r = mid - 1;
                    else l = mid + 1;
            }
            return false;    
    }
    
    int main() 
    {
            
            read(n); read(m);
            for (i = 1; i <= n; i++) read(a[i]);
            x.push_back(0);
            for (i = 1; i <= n / 2; i++)
            {
                    len = x.size();
                    for (j = 0; j < len; j++)
                    {
                            x.push_back(x[j]+a[i]);
                            x.push_back(x[j]-a[i]);
                    }
            }
            y.push_back(0);
            for (i = n / 2 + 1; i <= n; i++)
            {
                    len = y.size();
                    for (j = 0; j < len; j++)
                    {
                            y.push_back(y[j]+a[i]);
                            y.push_back(y[j]-a[i]);    
                    }    
            }    
            sort(x.begin(),x.end());
            unique(x.begin(),x.end());
            sort(y.begin(),y.end());
            unique(y.begin(),y.end());
            for (i = 1; i <= m; i++)
            {
                    flag = false;
                    read(w);
                    for (j = 0; j < x.size(); j++)
                    {
                            t = w - x[j];
                            if (search(t))
                            {
                                    flag = true;
                                    break;
                            }
                    }        
                    if (flag) printf("YES
    ");
                    else printf("NO
    ");
            }
            
            return 0;
        
    }


  • 相关阅读:
    [LeetCode] Maximum Depth of Binary Tree
    [LeetCode] Binary Tree Level Order Traversal II
    阿里第一天——maven学习
    微博用户行为分析
    对节目微博进行强过滤之后的处理
    关于推荐和机器学习的几个网站
    大论文微博个性化
    新浪微博用户分析
    位运算符规律小结
    字符串类常见面试大题
  • 原文地址:https://www.cnblogs.com/evenbao/p/9196286.html
Copyright © 2020-2023  润新知