小G的LY数对 非正解做法:unordered_map + 剪枝优化常数

由于本人过于菜鸡,没有想到正解做法,只想到了比较暴力的做法:用 unordered_map 存下所有数组 a 中各数的个数,然后对于数组 b 中的数暴力枚举修改的两位,然后在 unordered_map 查询对应数的个数加到答案中,复杂度

#include <bits/stdc++.h>
using namespace std;

const int N=300010;

int n,m,a[N],b[N];
unordered_map<int,int> cnt;

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        cnt[a[i]]++;
    }
    long long ans=0;
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&b[i]);
        bitset<30> bi=b[i];
        for (int x=0;x<30;x++)
        {
            for (int y=0;y<x;y++)
            {
                bitset<30> t=bi;
                t.flip(x); t.flip(y);
                int c=t.to_ulong();
                ans+=cnt[c];
            }
        }
    }
    printf("%lld\n",ans);
    getchar(); getchar();
    return 0;
}

然后喜闻乐见的 T 了(
由于 unordered_map 常数较大,因此考虑在这上面优化。可以发现,在枚举 b 数组的所有修改方案时,有相当多的方案是数组 a 没有的,也就是不在 unordered_map 中。对于不在 unordered_map 中的数,如果直接跳过查询的话,会减少很多不必要的时间开销。
那么怎么判断某个数 a 数组中有没有呢?开 大小的数组内存是不够的,这时就要用上 bitset 神器了。

#include <bits/stdc++.h>
using namespace std;

const int N=300010;

int n,m,a[N],b[N];
unordered_map<int,int> cnt;
bitset<1<<30> vis;

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        vis.set(a[i]);
        cnt[a[i]]++;
    }
    long long ans=0;
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&b[i]);
        bitset<30> bi=b[i];
        for (int x=0;x<30;x++)
        {
            for (int y=0;y<x;y++)
            {
                bitset<30> t=bi;
                t.flip(x); t.flip(y);
                int c=t.to_ulong();
                if (vis[c]) ans+=cnt[c];
            }
        }
    }
    printf("%lld\n",ans);
    getchar(); getchar();
    return 0;
}

跑得还挺快,不到 500ms,不知道能不能卡掉。