• Comet OJ


    题目描述

    求(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
    ",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
    ",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
    ",work(N+M)-work(N-M-1));
    	}
    }
    
  • 相关阅读:
    NCNN优化实时面部关键点检测
    使用 div 标签 contenteditable="true" 实现一个 聊天框,支持 Ctrl + v 粘贴图片
    《精益创业》读书总结
    DATAX使用
    canal增量同步原理以及使用说明
    element rules required 自定义表达式
    JavaScript 数组映射,重新整理
    wangeditor遮挡其他控件
    多个axios按顺序执行
    .NET Core 中基于 IHostedService 实现后台定时任务
  • 原文地址:https://www.cnblogs.com/gmh77/p/11962562.html
Copyright © 2020-2023  润新知