Transform
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 491 Accepted Submission(s): 171
Problem Description
A list of
n
integers are given. For an integer
x
you can do the following operations:
+ let the binary representation of
x
be
b31b30...b0¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ , you can flip one of the bits.
+ let
y
be an integer in the list, you can change
x
to
x⊕y , where
⊕
means bitwise exclusive or operation.
There are several integer pairs
(S,T) . For each pair, you need to answer the minimum operations needed to change
S
to
T .
Input
There are multiple test cases. The first line of input contains an integer
T
(T≤20) , indicating the number of test cases. For each test case:
The first line contains two integer
n
and
m
(1≤n≤15,1≤m≤105)
-- the number of integers given and the number of queries. The next line contains
n integers
a1,a2,...,an
(1≤ai≤105) , separated by a space.
In the next
m
lines, each contains two integers
si
and
ti
(1≤si,ti≤105) , denoting a query.
Output
For each test cases, output an integer
S=(∑i=1mi⋅zi) mod (109+7) , where
zi
is the answer for
i -th query.
Sample Input
Sample Output
10
Hint
$3 \to 4$ (2 operations): $3 \to 7 \to 4$ $1 \to 2$ (1 operation): $1 \oplus 3 = 2$ $3 \to 9$ (2 operations): $3 \to 1 \to 9$
Source
BestCoder Round #74 (div.2)
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 0, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int casenum, casei;
int n, m;
int a[40];
int f[1 << 17];
queue<int>q;
inline void inq(int x, int step)
{
if (~f[x])return;
f[x] = step;
q.push(x);
}
void bfs()
{
MS(f, -1); f[0] = 0;
for (int i = 0; i <= n; ++i)inq(a[i], 1);
while (!q.empty())
{
int x = q.front(); q.pop();
for (int i = 0; i <= n; ++i)inq(x^a[i], f[x] + 1);
}
}
void datamaker()
{
puts("1");
puts("15 90000"); n = 15; m = 90000;
for (int i = 1; i < n; ++i)
{
printf("%d ",1<<i );
}printf("%d\n",1<<n);
for (int i = 1; i <= m; ++i)
{
printf("%d %d\n", 1, 1 ^ i);
}
}
int main()
{
//fre(); datamaker(); return 0;
//0~16
for (int i = 0; i <= 16; ++i)a[i] = 1 << i;
scanf("%d", &casenum);
for (casei = 1; casei <= casenum; ++casei)
{
scanf("%d%d", &n, &m);
for (int i = 16+1; i <= 16+n; ++i)scanf("%d", &a[i]);
n += 16;
bfs();
int ans = 0;
for (int i = 1; i <= m; ++i)
{
int s, t;
scanf("%d%d", &s, &t);
LL v = f[s^t];
ans = (ans + i*v) % Z;
}
printf("%d\n", ans);
}
return 0;
}
/*
【trick&&吐槽】
1e5中的二的幂数最大是1<<16==65536
于是我们可能出现的最大异或数是(1<<17)-1
数组不要开小了
【题意】
T组数据。对于每组数据——
有n个数a[],m个询问。(1<=n<=15,1<=m<=1e5)
对于每个询问,问你从s到t的最小异或步数(1<=s,t<=n)
有两种操作:
1,选择某个二进制表示反转一位
2,把x变为x^a[]
【类型】
bfs
【分析】
选择某个二进制为反转一位,其实就等价于^1 or ^2 or ^4 ...
即我们a[]可以再选择[0,16]中的一个。
即我们一共有32个数,我们求从s到t的最小异或步数
我们只要达到s^t即可。
于是我们用这32个数做bfs,求得达到某个数的最小异或步数。
然后每次输出f[s^t]即可
【时间复杂度&&优化】
O(1e5*32)
【数据】
1
2 1
65536 65535
65536 65535
*/