Pair (binary digits treatment + dp) (2019 cattle off summer school and more training camp (seventh))

Example:

Input:

3
3 4 2
4 5 2
7 8 5

Output: 5731

Meaning of the questions: How much presence of x & y> C or x ^ y <C of <x, y> satisfying. (0 <x <= A, 0 <y <= B)

Solution: First consider the reverse, to find the number of (x, y) satisfying x & y <= C and x ^ y> = C, then A * B can be subtracted from it. Then is the digital template title dp (digital dp not know what knowledge can be the first meeting to look at this question), represents the first pos position with dp [pos] [ia] [ ib] [iand] [ixor] number, ia bit indicating whether an upper limit of a, ib indicating whether an upper limit of B, IAND indicating whether the ceiling is C, ixor indicating whether the lower limit of the exclusive oR C, (when the process is not a one to upper and lower limits, i.e., upper and lower limits which values can be easily, but not to solve // printf () in ( "dp [% d] [ % d] [% d] [% d] [% d] =% lld \ n", pos, i, j , i & j, i ^ j , ans); slash removed during input see example) as the input a value represented by dp, B, C are, therefore every time memset opposite -1. Because there dfs x or y is zero. And x, minimum y is 1, to lose x or y is zero. x is the number 0 are max (0, B-C + 1), i.e. y> = C; Similarly, y is 0 there max (0, A-C + 1) thereof.

code:

 

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL A,B,C,dp[40][2][2][2][2];
int t,a[40],b[40],c[40];
LL solve(int pos,int ia,int ib,int iand,int ixor)
{
    if(pos<0)return 1;
    if(dp[pos][ia][ib][iand][ixor]!=-1)return dp[pos][ia][ib][iand][ixor];
    int up1=1,up2=1,up3=1,up4=0;
    if(ia)up1=a[pos];//如果ia/ib/iand/ixor为0,即此处无上下限约束
    if(ib)up2=b[pos];
    if(iand)up3=c[pos];
    if(ixor)up4=c[pos];
    LL ans=0;
    for(int i=0;i<=up1;i++){
        for(int j=0;j<=up2;j++){
            if((i&j)>up3)continue;
            if((i^j)<up4)continue;
            ans+=solve(pos-1,ia&&(i==a[pos]),ib&&(j==b[pos]),iand&&((i&j)==c[pos]),ixor&&((i^j)==c[pos]));
            //printf("dp[%d][%d][%d][%d][%d]=%lld\n",pos,i,j,i&j,i^j,ans);
        }
    }
    return dp[pos][ia][ib][iand][ixor]=ans;
}
int main()
{
    scanf("%d",&t);
    while(t--){
        memset(dp,-1,sizeof(dp));
        scanf("%lld%lld%lld",&A,&B,&C);
        LL tA=A,tB=B,tC=C;
        memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(c,0,sizeof(c));
        int i=0,j=0,k=0;
        while(tA||tB||tC){//处理A,B,C的二进制
            if(tA){a[i++]=tA&1;tA=tA>>1;}
            if(tB){b[j++]=tB&1;tB=tB>>1;}
            if(tC){c[k++]=tC&1;tC=tC>>1;}
        }
        LL summ=solve(30,1,1,1,1)-max(A-C+1,0LL)-max(B-C+1,0LL);
        summ=(A*B)-summ;
        printf("%lld\n",summ);
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/Aamir-Dan/p/11364052.html