Xor HDU - 6899
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Xor HDU - 6899相关的知识,希望对你有一定的参考价值。
题意:
给你A,B,K,W,问现在有多少个(x,y)满足下列形式?
- x,y都是整数
- x∈[0,A],y∈[0,B]
- |x-y|<=k
- x xor y<=W
题解:
数位dp
对于第1,2,4都是经典的数位dp转移
对于第三点怎么转移?
我们将绝对值拆开,得到
x
−
y
<
=
k
,
y
−
x
<
=
k
x-y<=k,y-x<=k
x−y<=k,y−x<=k
整理下:
k
+
y
−
x
>
=
0
,
k
−
y
+
x
>
=
0
k+y-x>=0,k-y+x>=0
k+y−x>=0,k−y+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的主要内容,如果未能解决你的问题,请参考以下文章