Comet OJ - Contest #12 D

戏子无情 提交于 2019-12-06 04:45:54

题目描述

求(x,y)的对数满足x∈[0,a],y∈[0,b],x⊕y=0且|x-y|<=m

题解

一种比较sb的做法是考虑x-y的借位,根据借位以及差值进行转移

还有一种比较正常的做法,假设一开始x=0,y=n,那么就需要把y的某一些1移到x上,也就是对于(x-y)加上2^(i+1)

设加的数之和为s,那么需要保证|s-n|<=m,也就是n-m<=s<=n+m

注意是当n的第i位为1时才可以加上2^(i+1),把上界右移一位后就变成加上2^i

设f[i][0/1][0/1][0/1],表示当前到第i位,x、y、s是否顶住上界

枚举第i位的xy所选,使得x[i]^y[i]=n[i]且新的s不会越界即可

code

sb版

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
using namespace std;

int a[60];
int b[60];
int x[60];
int y[60];
long long f[61][2][2][2][2];
int T,i,j,k,l,I,J,K,L,p,q,P,Q,fs,ll;
long long n,m,A,B,ans;

int swap(int &x,int &y)
{
    int z=x;
    x=y;
    y=z;
}

void work()
{
    memset(f,0,sizeof(f));
    f[60][0][0][0][0]=1;
    fd(i,60,1)
    {
        I=i-1;
        
        fo(j,0,1)
        {
            fo(k,0,1)
            {
                fo(p,0,1)
                {
                    fo(q,0,1)
                    if (f[i][j][k][p][q])
                    {
                        if (!a[I])
                        {
                            if (j && !b[I]) continue;
                            
                            fo(l,0,1)
                            if ((p || x[I]>=l) && (q || y[I]>=l))
                            {
                                if (!j && b[I]>0) K=1; else K=k;
                                if (x[I]>l) P=1; else P=p;
                                if (y[I]>l) Q=1; else Q=q;
                                
                                f[I][j][K][P][Q]+=f[i][j][k][p][q];
                            }
                        }
                        else
                        {
                            if (I==fs) ll=1;
                            else ll=0;
                            
                            fo(l,ll,1)
                            if ((p || x[I]>=l) && (q || y[I]>=(1-l)))
                            {
                                if (!l)
                                {
                                    if (!j)
                                    J=0,K=1;
                                    else
                                    {
                                        if (b[I])
                                        J=0,K=k;
                                        else
                                        J=1,K=k;
                                    }
                                }
                                else
                                {
                                    if (j && !b[I]) continue;
                                    
                                    if (k)
                                    J=0,K=1;
                                    else
                                    {
                                        if (!b[I])
                                        {
                                            if (j)
                                            continue;
                                            else
                                            J=1,K=0;
                                        }
                                        else
                                        {
                                            if (j)
                                            continue;
                                            else
                                            J=0,K=0;
                                        }
                                    }
                                }
                                if (x[I]>l) P=1; else P=p;
                                if (y[I]>(1-l)) Q=1; else Q=q;
                                
                                f[I][J][K][P][Q]+=f[i][j][k][p][q];
                            }
                        }
                    }
                }
            }
        }
    }
    
    fo(k,0,1)
    {
        fo(p,0,1)
        {
            fo(q,0,1)
            ans+=f[0][0][k][p][q];
        }
    }
}

int main()
{
    scanf("%d",&T);
    for (;T;--T)
    {
        scanf("%lld%lld%lld%lld",&A,&B,&n,&m);
        
        fs=-1;
        
        fo(i,0,59)
        {
            a[i]=n&1;
            n>>=1;
            
            if (a[i])
            fs=i;
        }
        
        if (fs==-1)
        {
            printf("%lld\n",min(A,B)+1);
            continue;
        }
        
        fo(i,0,59) b[i]=m&1,m>>=1;
        fo(i,0,59) x[i]=A&1,A>>=1;
        fo(i,0,59) y[i]=B&1,B>>=1;
        
        ans=0;
        work();
        
        fo(i,0,59)
        swap(x[i],y[i]);
        
        work();
        
        printf("%lld\n",ans);
    }
}

正常版

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std;

int a[61];
int x[61];
int y[61];
int z[61];
long long f[61][2][2][2];
int T,i,j,k,l,I,J,K,L,s,S,X,Y,X2,Y2;
long long N,M,A,B,s1;

void turn(int *a,long long s)
{
    int i;
    
    fo(i,1,60)
    a[i]=s%2,s/=2;
}

long long work(long long t)
{
    long long ans=0;
    
    if (t>=0)
    {
        t/=2;
        turn(a,t);
    }
    else
    return 0;
    
    memset(f,0,sizeof(f));
    f[60][0][0][0]=1;
    
    fd(i,60,1)
    {
        I=i-1;
        
        fo(j,0,1)
        {
            fo(k,0,1)
            {
                fo(l,0,1)
                if (f[i][j][k][l])
                {
                    if (j) X2=1; else X2=x[i];
                    if (k) Y2=1; else Y2=y[i];
                    
                    fo(X,0,X2)
                    {
                        if (X<x[i]) J=1; else J=j;
                        
                        fo(Y,0,Y2)
                        if ((X^Y)==z[i] && !(!l && X && !Y && !a[i]))
                        {
                            if (Y<y[i]) K=1; else K=k;
                            if ((X && !Y)<a[i]) L=1; else L=l;
                            
                            f[I][J][K][L]+=f[i][j][k][l];
                        }
                    }
                }
            }
        }
    }
    
    fo(j,0,1)
    {
        fo(k,0,1)
        {
            fo(l,0,1)
            ans+=f[0][j][k][l];
        }
    }
    
    return ans;
}

int main()
{
    scanf("%d",&T);
    for (;T;--T)
    {
        scanf("%lld%lld%lld%lld",&A,&B,&N,&M);
        turn(x,A);
        turn(y,B);
        turn(z,N);
        
        printf("%lld\n",work(N+M)-work(N-M-1));
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!