有一个不知道怎么得出来的结论:A(x,y)=(x−1) xor (y−1)+1
如果知道这个了就好做了,题目转换为求∑ni=0∑mj=0[i xor j≤ K-1]∗(i xor j+1)
然后就是数位DP了,x,y一起一位一位填,f[i][0/1][0/1][0/1],3 个 0/1 分别表示x,y,x xor y 目前是否有卡在上界的。需要维护和以及个数。
dp1维护个数因为后面有个加一,dp2维护sum,注意坐标减一以及k减一
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
using namespace std;
int q;
long long mod=1e9+7;
long long dp1[35][2][2][2];
long long dp2[35][2][2][2];
long long cal(int x,int y,int k)
{
if(x<0 || y<0)
return 0;
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
dp1[32][1][1][1]=1;
for(int i=32;i>=1;i--)
{
for(int j1=0;j1<2;j1++)
for(int j2=0;j2<2;j2++)
for(int j3=0;j3<2;j3++)
if(dp1[i][j1][j2][j3])
{
for(int a1=0;a1<2;a1++)
for(int a2=0;a2<2;a2++)
{
if(j1&&a1>((x>>i-1)&1)) continue;
if(j2&&a2>((y>>i-1)&1)) continue;
if(j3&&(a1^a2)>((k>>i-1)&1)) continue;
int A=(j1&&(a1==((x>>i-1)&1)));
int B=(j2&&(a2==((y>>i-1)&1)));
int C=(j3&&(a1^a2)==((k>>i-1)&1));
dp1[i-1][A][B][C]=(dp1[i-1][A][B][C]+dp1[i][j1][j2][j3])%mod;
dp2[i-1][A][B][C]=(dp2[i-1][A][B][C]+dp2[i][j1][j2][j3]*2+(a1^a2)*dp1[i][j1][j2][j3])%mod;
}
}
}
long long ans=0;
for(int j1=0;j1<2;j1++)
for(int j2=0;j2<2;j2++)
for(int j3=0;j3<2;j3++)
ans=(ans+dp1[0][j1][j2][j3]+dp2[0][j1][j2][j3])%mod;
return ans;
}
int main()
{
while(~scanf("%d",&q))
{
while(q--)
{
int x1,y1,x2,y2,k;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k);
x1--;x2--;y1--;y2--;k--;
long long ans=(((cal(x2,y2,k)-cal(x1-1,y2,k)-cal(x2,y1-1,k)+cal(x1-1,y1-1,k))%mod)+mod)%mod;
printf("%lld\n",ans);
}
}
}