H Pair 数位dp

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));
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值