这个东西就是(x−1) xor (y−1)+1
然后转化为 ∑i∑j[i xor j≤k]和∑i∑j[i xor j≤k]∗(i xor j)
这个东西 数位dp下就好了
代码常数略大 但是还是很好看的
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
#define read(x) scanf("%d",&(x))
const int P=1e9+7;
ll sum[35][2][2][2],cnt[35][2][2][2];
inline ll Calc(int _x,int _y,int _K){
if (_x==-1 || _y==-1) return 0;
int x[35]={0},y[35]={0},K[35]={0},_p=0;
_p=-1; while (_x) x[++_p]=_x&1,_x>>=1;
_p=-1; while (_y) y[++_p]=_y&1,_y>>=1;
_p=-1; while (_K) K[++_p]=_K&1,_K>>=1;
cl(sum); cl(cnt);
cnt[31][0][0][0]=1;
for (int i=31;i;i--)
for (int t1=0;t1<2;t1++)
for (int t2=0;t2<2;t2++)
for (int t3=0;t3<2;t3++){
for (int a=0;a<=(t1?1:x[i-1]);a++)
for (int b=0;b<=(t2?1:y[i-1]);b++){
if ((a^b)>(t3?1:K[i-1])) continue;
int nt1=t1|(a<x[i-1]),nt2=t2|(b<y[i-1]),nt3=t3|((a^b)<K[i-1]);
(cnt[i-1][nt1][nt2][nt3]+=cnt[i][t1][t2][t3])%=P;
(sum[i-1][nt1][nt2][nt3]+=sum[i][t1][t2][t3]+cnt[i][t1][t2][t3]*((a^b)<<(i-1))%P)%=P;
}
}
ll Sum=0,Cnt=0;
for (int t1=0;t1<2;t1++)
for (int t2=0;t2<2;t2++)
for (int t3=0;t3<2;t3++)
(Sum+=sum[0][t1][t2][t3])%=P,(Cnt+=cnt[0][t1][t2][t3])%=P;
return (Sum+Cnt)%P;
}
int main(){
int Q,x1,x2,y1,y2,K;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(Q);
while (Q--){
read(x1); read(y1); read(x2); read(y2); read(K); x1--; y1--; x2--; y2--; K--;
printf("%I64d\n",(Calc(x2,y2,K)+P-Calc(x2,y1-1,K)+P-Calc(x1-1,y2,K)+Calc(x1-1,y1-1,K))%P);
}
return 0;
}
本文介绍了一个使用数位动态规划方法解决特定XOR运算计数问题的算法。该算法通过预处理和递归计算的方式,在多项式时间内找到两个整数范围内所有可能的XOR值不超过某一阈值的数量及其总和。

258

被折叠的 条评论
为什么被折叠?



