【noip模拟赛 化零】 题解

Describe

有5个集合,每个集合N个元素,从每个集合选出一个数,共5个,问是否可以使和为0。

IN put:

第一行一个整数 N,表示集合的大小。

接下来五行每行 N个整数,表示这五个集合内的元素。

OUT put:

如果能找到符合条件的五个数,则输出“YES”,否则输出“NO”。

example:

in
3
1 -2 9
-1 2 1
-3 5 1
-1 7 6
-4 -1 -7
out
YES

数据范围:

N<=20 30%
N<=200 100%

题解:

考虑 N <= 20 直接N^5暴力

对于 N > 20 考虑一种赌博式的想法

如果有合法解的话,不妨设在前两个集合和后三个集合存在相反数

这样我们可以预先处理出N^2 和 N^3 的方案数,再进行组合,看是否有相反数

这时候我们先排序再套个lower_bound就ok了

最差在没有解大概跑了1.11s

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn = 210;
ll a[maxn], b[maxn], c[maxn], d[maxn], e[maxn], n;
ll ans1[41000], ans2[8000100], cnt1 = 0, cnt2 = 0;
inline ll read()
{
    ll k=0,f=1;
    char c=getchar();
    while(!isdigit(c))
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(isdigit(c))
    {
        k=(k<<1)+(k<<3)+c-48;
        c=getchar();
    }
    return k*f;
}
int main()
{
    n = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    for(int i = 1; i <= n; i++) b[i] = read();
    for(int i = 1; i <= n; i++) c[i] = read();
    for(int i = 1; i <= n; i++) d[i] = read();
    for(int i = 1; i <= n; i++) e[i] = read();
    
    if(n <= 25)
    {
        for(int v = 1; v <= n; v++)
            for(int w = 1; w <= n; w++)
                for(int x = n; x >= 1; x--)
                    for(int y = n; y >= 1; y--)
                        for(int z = n; z >= 1; z--)
                        {
                            if(a[v] + b[w] + c[x] + d[y] + e[z] == 0)
                            {
                                cout<<"YES"<<endl;
                                return 0;
                            }
                        }
        cout<<"NO"<<endl;
        return 0;
    }
    else
    {
        for(int v = 1; v <= n; v++)
            for(int w = 1; w <= n; w++)
                ans1[++cnt1] = a[v]+b[w];
        for(int x = 1; x <= n; x++)
                for(int y = 1; y <= n; y++)
                    for(int z = 1; z <= n; z++)
                    ans2[++cnt2] = -1*(c[x]+d[y]+e[z]);
        sort(ans1+1, ans1+1+cnt1);
        for(int i = 1; i <= cnt2; i++)
            {
                int now = lower_bound(ans1+1, ans1+1+cnt1, ans2[i])-ans1;
                if(ans1[now] == ans2[i])
                {
                    cout<<"YES"<<endl;
                    return 0;
                }
            }
            
        cout<<"NO"<<endl;
        return 0;
    }
}

猜你喜欢

转载自www.cnblogs.com/MisakaAzusa/p/9790126.html