H Pair
题意不多说,题目直接告诉你了。
题解:我们求它的反面,我之前做的数位dp都是可以用反面求更简单,我们找出(x&y)<=C和(x^y)>= C,为啥要反面呢???,因为反面可以无脑当pos超过边界时return 1,因为不合法的情况我们continue了,这是对所有的数位dp都是一样的。那我们设dp[pos][sta1][sta2][lim1][lim2],sta1=0代表(x&y)=C,sta1=1代表(x&y) < C,sta2 = 0 代表(x^y)= C , sta2 = 1代表(x^y) > C。那么如果sta1=0且(a[i]&b[i])> c[i] 就continue;同样对于另一种情况。
提醒:理论上来讲总数是a*b,但是因为你数位Dp多算进了x=0和y=0的两种情况的数量。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll dp[32][2][2][2][2];
int x1[32],x2[32];
int c;
ll dfs(int pos,int sta1,int sta2,int lim1,int lim2)
{
if(pos==0) return 1;
if(dp[pos][sta1][sta2][lim1][lim2]!=-1) return dp[pos][sta1][sta2][lim1][lim2];
int up1 = lim1==1?x1[pos]:1;
int up2 = lim2==1?x2[pos]:1;
ll ans = 0;
for(int i=0;i<=up1;i++)
for(int j=0;j<=up2;j++)
{
int xka = 0;
if(c>>(pos-1)&1) xka = 1;
if((i&j)>xka&&!sta1) continue;
if((i^j)<xka&&!sta2) continue;
int tmp1,tmp2;
tmp1 = sta1||(i&j)<xka;
tmp2 = sta2||(i^j)>xka;
ans += dfs(pos-1,tmp1,tmp2,lim1&&(i==up1),lim2&&(j==up2));
}
return dp[pos][sta1][sta2][lim1][lim2] = ans;
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
int a,b;
scanf("%d%d%d",&a,&b,&c);
ll tot = 1LL*a*b + max(a-c+1,0) + max(b-c+1,0);
memset(dp,-1,sizeof(dp));
for(int i=0;i<32;i++) x1[i] = x2[i] = 0;
for(int i=1;a;i++,a/=2)
x1[i] = a%2;
for(int i=1;b;i++,b/=2)
x2[i] = b%2;
printf("%lld\n",tot-dfs(30,0,0,1,1));
}
}