HDU 5637:Transform

来源:互联网 发布:php网店系统源码 网畅 编辑:程序博客网 时间:2024/05/14 05:24

Transform

 
 Accepts: 47
 
 Submissions: 187
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
给出nn个整数, 对于一个整数xx, 你可以做如下的操作若干次:  + 令xx的二进制表示为\overline{b_{31}b_{30}...b_0}b31b30...b0, 你可以翻转其中一个位.  + 令yy是给出的其中一个整数, 你可以把xx变为x \oplus yxy, 其中\oplus表示位运算里面的异或操作.现在有若干整数对(S, T)(S,T), 对于每对整数你需要找出从SS变成TT的最小操作次数.
输入描述
输入包含多组数据. 第一行有一个整数TT (T \le 20)(T20), 表示测试数据组数. 对于每组数据:第一行包含两个整数nnmm (1 \le n \le 15, 1 \le m \le 10^5)(1n15,1m105), 表示给出整数的数目和询问的数目. 接下来一行包含nn个用空格分隔的整数a_1, a_2, ..., a_na1,a2,...,an (1 \le a_i \le 10^5)(1ai105).接下来mm行, 每行包含两个整数s_isit_iti (1 \le s_i, t_i \le 10^5)(1si,ti105), 代表一组询问.
输出描述
对于每组数据, 输出一个整数S=(\displaystyle\sum_{i=1}^{m} i \cdot z_i) \text{ mod } (10^9 + 7)S=(i=1mizi) mod (109+7), 其中z_izi是第ii次询问的答案.
输入样例
13 31 2 33 41 23 9
输出样例
10
Hint
3 \to 434 (2次操作): 3 \to 7 \to 43741 \to 212 (1次操作): 1 \oplus 3 = 213=23 \to 939 (2次操作): 3 \to 1 \to 9319

注意到x^a^b^c^d...=y即 a^b^c^d...=x^y所以直接宽搜结果,O(1)查询。

代码:

#pragma warning(disable:4996)#include <iostream>#include <functional>#include <algorithm>#include <cstring>#include <vector>#include <string>#include <cstdio>#include <cmath>#include <queue>#include <stack>#include <deque>#include <set>#include <map>using namespace std;typedef long long ll;#define INF 0x3fffffffffffffffconst ll mod = 1e9 + 7;const int maxn = 1e5 + 5;int n, m;int val[20], dis[1 << 17];queue<int>qu;void cal(){    int i, j, k, s;    memset(dis, -1, sizeof(dis));    while (!qu.empty())qu.pop();    dis[0] = 0;    qu.push(0);    while (!qu.empty())    {        int k = qu.front();        qu.pop();        for (i = 0; i < 17; i++)        {            s = k ^ (1 << i);            if (dis[s] == -1)            {                dis[s] = dis[k] + 1;                qu.push(s);            }        }        for (i = 1; i <= n; i++)        {            s = k^val[i];            if (dis[s] == -1)            {                dis[s] = dis[k] + 1;                qu.push(s);            }        }    }}void solve(){    int i, j, k;    int u, v;    scanf("%d%d", &n, &m);    for (i = 1; i <= n; i++)    {        scanf("%d", &val[i]);    }        cal();        ll ans = 0, res;    for (k = 1; k <= m; k++)    {        scanf("%d%d", &u, &v);        res = dis[u^v];        ans = (ans + (ll)(res*k)%mod) % mod;    }    printf("%lld\n", ans);}int main(){#ifndef ONLINE_JUDGE      freopen("i.txt", "r", stdin);    freopen("o.txt", "w", stdout);#endif     int t;    scanf("%d", &t);    while (t--)    {        solve();    }    return 0;}


0 0
原创粉丝点击