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


原文地址:https://www.cnblogs.com/evenbao/p/9196286.html