HDU 5637 Transform

题意: 有两种变换:

  1. 改变此数二进制的某一位(1变成0 或者 0变成1)

  2. 让它与给出的n个数当中的任意一个做异或运算

给你两个数s, t,求从s到t最少要经过几步变换,一共m组查询
思路: 仔细观察会发现其实只与(s^t)有关,那么设x = s^t,那么x就是s和t二进制之间的差别(仔细想想就是s和t相同的位都是0, 不同的都是1,说明只要需要发生变化的位都是1),那么只需要用s^x就得到t了,所以只需要求最少变成x需要多少步,然后再加1就是答案了,那么答案就是从0变成x需要多少步。bfs一下即可。不过还要注意第一个变化条件,在bfs的写出来。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define pii pair<int, int>
using namespace std;

const int maxn = 1e6;
const long long mod = 1e9 + 7;
int res[maxn];
int a[20];
void bfs(int n)
{
    memset(res, -1, sizeof(res));
    res[0] = 0;
    queue<pii> Q;
    pii cur, nex;
    cur.first = cur.second = 0;
    Q.push(cur);
    int x = (1 << 17);
    while (!Q.empty())
    {
        cur = Q.front(); Q.pop();
        for (int i = 0; i < n; i++)
        {
            nex.first = cur.first ^ a[i];
            nex.second = cur.second + 1;
            if (nex.first < x && res[nex.first] == -1)
            {
                res[nex.first] = nex.second;
                Q.push(nex);
            }
        }
        for (int j = 0; j < 17; j++)
        {
            nex.first = cur.first ^ (1 << j);
            nex.second = cur.second + 1;
            if (nex.first < x && res[nex.first] == -1)
            {
                res[nex.first] = nex.second;
                Q.push(nex);
            }
        }
    }
}
int main()
{
    int T, n, m, s, t;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++) scanf("%d", &a[i]);
        bfs(n);
        long long ans = 0;
        for (int q = 1; q <= m; q++)
        {
            scanf("%d%d", &s, &t);
            t = s ^ t;
            ans = (ans + (long long)q * res[t]) % mod;
        }
        printf("%d\n", (int)ans);
    }

    return 0;
}
View Code

 

posted @ 2016-03-08 21:00  Howe_Young  阅读(257)  评论(0编辑  收藏  举报