[ SDOI 2016 ] 储能表
题目
思路
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
const int N = 65;
int f[N][2][2][2], g[N][2][2][2], T;
signed main() {
cin >> T;
for (int n, m, k, p; T-- && cin >> n >> m >> k >> p; ) {
memset(f, 0, sizeof f), memset(g, 0, sizeof g), g[61][1][1][1] = 1;
for (int i = 60; i >= 0; i--) {
int q = (n >> i) & 1, w = (m >> i) & 1, e = (k >> i) & 1;
for (int a = 0; a < 2; a++)
for (int b = 0; b < 2; b++)
for (int c = 0; c < 2; c++)
if (f[i + 1][a][b][c] || g[i + 1][a][b][c])
for (int x = 0; x < 2; x++)
for (int y = 0; y < 2; y++) {
int z = x ^ y;
if ((a && x > q) || (b && y > w) || (c && z < e)) continue;
int s = (a && x == q), u = (b && y == w), v = (c && z == e);
g[i][s][u][v] = (g[i][s][u][v] + g[i + 1][a][b][c]) % p;
f[i][s][u][v] = (f[i][s][u][v] + f[i + 1][a][b][c] +
(z - e + p) % p *
((1ll << i) % p) % p *
g[i + 1][a][b][c] % p) % p;
}
}
cout << f[0][0][0][0] << endl;
}
return 0;
}