题意: 给出 A, B, C, 求满足 1 <= x <= A , 1 <= y <= B 中 x & y > C | x ^ y < C的对数。
其中1 <= A, B, C <= 1e9.
思路: 反向思考,先求出 x & y <= C <= x ^ y的对数总数res, A * B - res就是答案.
求res的过程可考虑数位dp。先在a,b, c分解成二进制制数,考虑其上每一位与前一位的转移状态,一共有四种。
0 ai & bi = ci = ai ^ bi, 1 is ai & bi <= ci = ai ^ bi, ai & bi = ci <= ai ^ bi, 3 is ai & bi <= ci <= ai ^ bi
然后去掉全零的答案。
AC code:
#include
using namespace std;
typedef long long ll;
int numa[32], numb[32], numc[32];
ll dp[35][4][2][2][2][2];
ll dfs(int pos, int sta, bool limita, bool limitb, bool zeroa, bool zerob){
if(!~pos){
return !zeroa && !zerob; //去除前导零的答案
}
if(~dp[pos][sta][limita][limitb][zeroa][zerob]) return dp[pos][sta][limita][limitb][zeroa][zerob];
int upa = limita ? numa[pos] : 1;
int upb = limitb ? numb[pos] : 1;
ll res = 0;
for(int i = 0; i <= upa; ++i){
for(int j = 0; j <= upb; ++j){
int andv = i & j, xorv = i ^ j;
//0 ai & bi = ci = ai ^ bi, 1 is ai & bi <= ci = ai ^ bi, ai & bi = ci <= ai ^ bi, 3 is ai & bi <= ci <= ai ^ bi
if(sta == 0){
if(andv < numc[pos] && numc[pos] < xorv){
res += dfs(pos - 1, 3, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
}else if(andv < numc[pos] && numc[pos] == xorv){
res += dfs(pos - 1, 1, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
}else if(andv == numc[pos] && numc[pos] < xorv){
res += dfs(pos - 1, 2, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
}else if(andv == numc[pos] && numc[pos] == xorv){
res += dfs(pos - 1, 0, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
}
}else if(sta == 1){
if(numc[pos] < xorv){
res += dfs(pos - 1, 3, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
}else if(numc[pos] == xorv){
res += dfs(pos - 1, 1, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
}
}else if(sta == 2){
if(andv < numc[pos]){
res += dfs(pos - 1, 3, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
}else if(andv == numc[pos]){
res += dfs(pos - 1, 2, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
}
}else{
res += dfs(pos - 1, 3, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
}
}
}
return (dp[pos][sta][limita][limitb][zeroa][zerob] = res);
}
ll solve(int a, int b, int c){
memset(dp, -1, sizeof(dp));
for(int i = 31; ~i; --i){
numa[i] = ((a >> i) & 1);
numb[i] = ((b >> i) & 1);
numc[i] = ((c >> i) & 1);
}
return dfs(31, 0, 1, 1, 1, 1);
}
int main(){
int T;
scanf("%d", &T);
while(T--){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
ll ans = (ll)a * b - solve(a, b, c);
printf("%lld\n", ans);
}
return 0;
}