链接:https://ac.nowcoder.com/acm/contest/887/H
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
Given three integers Count the number of pairs <x, y> (with 1≤x≤A1)
such that at least one of the following is true:
("and", "xor" are bit operators)
输入描述:
The first line of the input gives the number of test cases, T (T≤100)T\ (T \leq 100)T (T≤100). test cases follow. For each test case, the only line contains three integers , and . 1≤A,B,C≤1091 \leq A,B,C \leq 10^91≤A,B,C≤109
输出描述:
For each test case, the only line contains an integer that is the number of pairs satisfying the condition given in the problem statement.
示例1
输入
复制
3 3 4 2 4 5 2 7 8 5
输出
复制
5 7 31
给定A, B, C,
需要求有多少个pair 满足 • x & y > C or x ^ y < C •
直接数位DP一下求解
当然以上是邝斌说的
------------------------------------------------------
这题不妨设d[i][alim][blim][sta1][sta2];
表示数位上第i位,a, b 分别被限制的状态, 以及 and 操作, xor操作目前的状态
0 表示已经不满足, 1 表示 正在比较可能满足 ,3表示已经满足了
显然对于每一位
1 如果之前已经不满足, 该位无论怎么样都不满足了
2 如果之前可能满足, 该位不满足, 则不满足, 若该位满足, 则满足
3 如果之前已经满足, 该位无论怎么样都满足
最后位数为0时, 只要sta1, sta2 有一个为2, 即满足。
因为数位dp时会算上x = 0, y = 0,C = 0 的情况, 所以最后要减去零的情况。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define continue(x) { x; continue; }
#define break(x) { x; break; }
const int N = 5e4 + 10;
int mod = 998244353;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
ll d[40][2][2][3][3]; // 0不满足 1可能满足 2 已经满足
int a[40];
int b[40];
int c[40];
ll dfs(int pos, int alim, int blim, int u, int v) // u == & v == ^
{
if (pos == 0)
return u == 2 || v == 2;
if (d[pos][alim][blim][u][v] != -1)
return d[pos][alim][blim][u][v];
int up1 = alim ? a[pos] : 1;
int up2 = blim ? b[pos] : 1;
ll sum = 0;
for (int i = 0; i <= up1; i++)
for (int j = 0; j <= up2; j++)
{
int nowu = u, nowv = v;
if ((i & j) > c[pos] && u)
nowu = 2;
if ((i & j) < c[pos] && u != 2)
nowu = 0;
if ((i ^ j) < c[pos] && v)
nowv = 2;
if ((i ^ j) > c[pos] && v != 2)
nowv = 0;
if (!nowu && !nowv)
continue;
sum += dfs(pos - 1, alim && i == up1, blim && j == up2, nowu, nowv);
}
return d[pos][alim][blim][u][v] = sum;
}
ll get_num(int x, int y, int z)
{
int cnt = 0;
memset(d, -1, sizeof d);
memset(a, 0, sizeof a);
memset(b, 0, sizeof b);
memset(c, 0, sizeof c);
int cnt1 = 0;
while (x)
a[++cnt1] = x % 2, x /= 2;
int cnt2 = 0;
while (y)
b[++cnt2] = y % 2, y /= 2;
int cnt3 = 0;
while (z)
c[++cnt3] = z % 2, z /= 2;
int M = max({ cnt1, cnt2, cnt3 });
return dfs(M, 1, 1, 1, 1);
}
int main(){
#ifdef LOCAL
freopen("D:/input.txt", "r", stdin);
#endif
int t;
cin >> t;
while (t--)
{
int A, B, C;
cin >> A >> B >> C;
ll zero = min(A, C - 1) + min(B, C - 1) + 1;
cout << get_num(A, B, C) - zero << endl;
}
return TIME;
}