[JZOJ100047] 【NOIP2017提高A组模拟7.14】基因变异
其实所有的操作都可以看成一个数亦或另一个数(显然)。
那么 : st ^ x1 ^ x2 ^ ... ^ xk = ed ,
两边同时异或$\large st$得到
x1 ^ x2 ^ ... ^ xk = ed ^ st。
所以我们只需要求出0变成st^ed的步数就行了。
考虑到n很小,1e6也最多是$\large 2^{20}$。
所以直接bfs一遍就可以每次$\large O(1)$求出答案。
#include <iostream> #include <cstdio> #include <queue> #include <ctime> using namespace std; #define reg register inline int read() { int res = 0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return res; } int n, Q; int a[25]; int dis[10000005]; bool vis[10000005]; int main() { // double ST = clock(); n = read(), Q = read(); for (reg int i = 1 ; i <= n ; i ++) a[i] = read(); queue <int> q; q.push(0); vis[0] = 1; while(!q.empty()) { int x = q.front();q.pop(); for (reg int i = 1 ; i <= n ; i ++) { int t = x ^ a[i]; if (t > 3000000) continue; if (vis[t]) continue; vis[t] = 1; dis[t] = dis[x] + 1; q.push(t); } for (reg int i = 1 ; i <= 25 ; i ++) { int t = x; int mark = (1 << i - 1); t ^= mark; if (t > 3000000) continue; if (vis[t]) continue; vis[t] = 1; dis[t] = dis[x] + 1; q.push(t); } } while(Q--) { int st = read(), ed = read(); printf("%d\n", dis[st ^ ed]); } // double ED = clock(); // printf("%.0lfms\n", ED - ST); return 0; }