【CodeChef】Strange Transform
阿新 • • 發佈:2018-11-19
【題目連結】
【思路要點】
- 若我們將每一位分開考慮,異或可以看做模 意義下的加法。
- 因此,一個位置 的值可以看做從 出發,每次可以選擇從 走到 ,最終停在 處的方案數對 取模。
- 因此, 。
- 注意到由 定理,當且僅當 在二進位制下數位包含 , ,上式有特殊情況: 。
- 現在我們來考慮一個詢問 ,由上面的推斷,我們令 不會使答案發生變化,下令 。
- 若 ,我們可以預處理出 的結果,直接查詢。
- 若 ,令 表示 最高的為 的位置,則有 ,遞迴求解即可。
- 時間複雜度 。
【程式碼】
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 5; const int MAXM = 512; const int goal = 511; const int Min = 262143; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, m, type; int a[MAXM][MAXN]; int work(int pos, int k) { if (k == 0) return a[type][pos]; int tmp = k & -k, ans = 0; ans ^= work(pos, k ^ tmp); if (pos + tmp <= n) ans ^= work(pos + tmp, k ^ tmp); return ans; } int main() { read(n), read(m); for (int i = 1; i <= n; i++) read(a[0][i]); for (int i = 1; i <= goal; i++) for (int j = 1; j <= n; j++) a[i][j] = a[i - 1][j] ^ a[i - 1][j + 1]; for (int i = 1; i <= m; i++) { int k, x; read(k), read(x); k &= Min, type = k & goal; writeln(work(x, k ^ type)); } return 0; }