HDU 5968 异或密码 预处理异或前缀和+枚举 or 预处理+二分

题目https://cn.vjudge.net/problem/HDU-5968

思路
思路一:利用异或运算 a^b^b = a的性质,O(n)预处理出异或的前缀,即可O(1)查询区间连续异或值。之后对于给出的x只需枚举所有子区间即可得到答案。总复杂度O(n + m*n^2)

思路二:直接预处理求出所有区间的异或值和区间长度,将其排序,对于输入的x,二分查找到与x作差绝对值最小的值,其对应的最长区间长度即为答案。

代码:C++
这里只给出思路一的代码

#include <cstdio>
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
#include <map>
#include <cstring>
#include <set>
#include <stack>
#include <cstdlib>
#include <bitset>
using namespace std;

const int maxn = 100 + 10;

int prexor[maxn];
int a[maxn];
int n;

inline int XOR(int l, int r)
{
    return prexor[r] ^ prexor[l-1];
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= n; i++)
        {
            prexor[i] = prexor[i-1] ^ a[i];
        }
        int m;
        scanf("%d", &m);
        while(m--)
        {
            int x;
            scanf("%d", &x);
            int ansval = (int)1e8;
            int anslen = 0;
            for(int i = 1; i <= n; i++)
            {
                for(int j = i; j <= n; j++)
                {
                    int t = abs(XOR(i, j) - x);
                    int len = j - i + 1;
                    if(t < ansval || (t == ansval && len > anslen))
                    {
                        ansval = t;
                        anslen = len;
                    }
                }
            }
            cout << anslen << endl;
        }
        cout << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Rewriter_huanying/article/details/81413871