Xor HDU - 6899

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Xor HDU - 6899相关的知识,希望对你有一定的参考价值。

Xor HDU - 6899

题意:

给你A,B,K,W,问现在有多少个(x,y)满足下列形式?

  1. x,y都是整数
  2. x∈[0,A],y∈[0,B]
  3. |x-y|<=k
  4. x xor y<=W

题解:

数位dp
对于第1,2,4都是经典的数位dp转移
对于第三点怎么转移?
我们将绝对值拆开,得到 x − y < = k , y − x < = k x-y<=k,y-x<=k xy<=k,yx<=k
整理下: k + y − x > = 0 , k − y + x > = 0 k+y-x>=0,k-y+x>=0 k+yx>=0,ky+x>=0
现在我们要让k+y-x>=0(暂先考虑这一个)
数位dp是按照每一位去考虑,那么k,x,y都是只能取0,1,那么也就是说k+y-x的取值范围是[-1,1],但是与异或不同,我们这个式子不能光看二进制运算,因为每位之间是由联系的,所以我们可以在转移时记录上个值的情况,用k1来记录,对于当前的值就是k1 * 2+val,(乘2是因为我们是二进制拆分的,所有还原时要乘回去)。如果k1<=-2,那必然没解,因为k1乘2后变成-4,而当前为k+y-x最大才是1,这样传下去还是负的,无法变正。如果k1>=1是一定有解的,因为怎么都是正数
与常规数位dp不同,本题牵扯了进位情况,第一次见,记录一下
详细看代码

代码:

#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{
    x= 0;
    char c= getchar();
    bool flag= 0;
    while (c < '0' || c > '9')
        flag|= (c == '-'), c= getchar();
    while (c >= '0' && c <= '9')
        x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();
    if (flag)
        x= -x;
    read(Ar...);
}
template <typename T> inline void write(T x)
{
    if (x < 0) {
        x= ~(x - 1);
        putchar('-');
    }
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#else
    startTime = clock ();
    freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#else
    endTime= clock();
    printf("\\nRun Time:%lfs\\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn=50;
ll dp[maxn][5][5][2][2][2];
ll a[maxn],b[maxn],k[maxn],w[maxn];
int p=1;//偏移量 
ll dfs(int len,int k1,int k2,int flag1,int flag2,int flag3){
	if(k1<=-2||k2<=-2)return 0; 
	if(len==-1)return (k1>=0&&k2>=0);
	if(dp[len][k1+p][k2+p][flag1][flag2][flag3]!=-1)return dp[len][k1+p][k2+p][flag1][flag2][flag3];
	int up1=flag1?a[len]:1;
	int up2=flag2?b[len]:1;
	int up3=flag3?w[len]:1;
	ll ans=0;
	for(int i=0;i<=up1;i++){
		for(int j=0;j<=up2;j++){
			if((i^j)>up3)continue;
				ans+=dfs(len-1,min(k1*2+i-j+k[len],1ll),min(k2*2+j-i+k[len],1ll),flag1&&(i==up1),flag2&&(j==up2),flag3&&((i^j)==w[len]));
		}
	}
	return dp[len][k1+p][k2+p][flag1][flag2][flag3]=ans;
}
ll solve(int A,int B,int K,int W){
	memset(dp,-1,sizeof(dp));
	for(int i=0;i<=30;i++){
		a[i]=(A&1);
		A>>=1;
		b[i]=(B&1);
		B>>=1;
		k[i]=(K&1);
		K>>=1;
		w[i]=(W&1);
		W>>=1;
	}
	ll ans=dfs(30,0,0,1,1,1);
	return ans;
}
int main()
{
    rd_test();
	int t;
	read(t);
	while(t--){
		ll A,B,K,W;
		read(A,B,K,W);
		cout<<solve(A,B,K,W)<<endl; 
	}
    //Time_test();
}




以上是关于Xor HDU - 6899的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4825 Xor Sum

HDU--4825 Xor Sum (字典树)

HDU 4825 Xor Sum(01字典树)题解

HDU - 3949 :XOR(线性基)

HDU5883 The Best Path(欧拉回路 | 通路下求XOR的最大值)

[hdu3949]XOR(线性基求xor第k小)