1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| #include <iostream> #include <cstdio> #include <cstring> #define maxn 70 #define ll long long using namespace std;
ll n, m, k; int p;
struct node { int s, v;
node() {} node(int _v, int _s) { v = _v; s = _s; } } f[maxn][2][2];
int d1[maxn], d2[maxn], d3[maxn]; node dfs(int pos, bool lim1, bool lim2, bool lim3) { if (!pos) return node(0, 1); if (!lim3 && (~f[pos][lim1][lim2].v || ~f[pos][lim1][lim2].s)) return f[pos][lim1][lim2]; int up1 = lim1 ? d1[pos] : 1, up2 = lim2 ? d2[pos] : 1; node ans = node(0, 0); for (int i = 0; i <= up1; ++i) for (int j = 0; j <= up2; ++j) { if (lim3 && (i ^ j) < d3[pos]) continue; node t = dfs(pos - 1, lim1 && i == d1[pos], lim2 && j == d2[pos], lim3 && (i ^ j) == d3[pos]); ans.s = (ans.s + t.s) % p; ans.v = (ans.v + t.v + (i ^ j) * (1ll << pos - 1) % p * t.s) % p; } if (!lim3) f[pos][lim1][lim2] = ans; return ans; }
node solve(ll x1, ll x2, ll x3) { int l1 = 0, l2 = 0, l3 = 0; memset(d1, 0, sizeof d1); memset(d2, 0, sizeof d2); memset(d3, 0, sizeof d3); while (x1) { d1[++l1] = x1 % 2; x1 /= 2; } while (x2) { d2[++l2] = x2 % 2; x2 /= 2; } while (x3) { d3[++l3] = x3 % 2; x3 /= 2; } int l = max(l1, max(l2, l3)); return dfs(l, 1, 1, 1); }
void mem() { for (int i = 0; i < maxn; ++i) for (int j = 0; j < 2; ++j) for (int k = 0; k < 2; ++k) f[i][j][k] = node(-1, -1); }
void work() { cin >> n >> m >> k >> p; --n; --m; mem(); node t = solve(n, m, k); cout << (t.v - t.s * (k % p) % p + p) % p << endl; }
int main() { int T; cin >> T; while (T--) work(); return 0; }
|