传送门
文章目录
- 题意:
- 思路:
题意:
问你有多少对x,yx,yx,y满足以下条件:
(1)x∈[0,A],y∈[0,B](1)x \in [0,A],y\in [0,B](1)x∈[0,A],y∈[0,B]
(2)∣x−y∣≤K(2)|x-y|\le K(2)∣x−y∣≤K
(3)xxory≤W(3)x \ \ xor \ \ y\le W(3)x xor y≤W
其中A,B,K,W≤1e9A,B,K,W\le 1e9A,B,K,W≤1e9。
思路:
明显的数位dpdpdp了,考虑怎么设计状态。
众嗦粥汁,数位dpdpdp的状态是要能表现出数的状态和结构的,分别分析一下这三个条件就好啦。
对于第一个条件,我们维护两个变量flag1,flag2flag1,flag2flag1,flag2表示能否达到上界就好啦,很套路。
对于第二个条件,我们自然的想到拆掉绝对值,变成x−y+K≥0,y−x+K≥0x-y+K\ge0,y-x+K\ge0x−y+K≥0,y−x+K≥0,由于我们需要按照二进制来考虑(因为有异或), 所以我这两个式子的值域都为[−1,2][-1,2][−1,2],所以我们分别用两个变量k1,k2k1,k2k1,k2表示这两个式子是多少。考虑是否每个状态都有意义呢?这里只考虑k1k1k1,当k1≤−2k1\le-2k1≤−2的时候,由于我们加上当前位的[−1,2][-1,2][−1,2]中某一个数之前需要乘222(因为从高位到低位),那么无论如何,这个值只会越来越小,所以如果k≤−2k\le-2k≤−2的时候直接返回000即可。对于大于000的状态,无论如何都不会变小,我们为了节省空间将其与222取一个minminmin即可。
对于第三个条件,记一个变量为flag3flag3flag3,表示WWW是否达到上界,也就是说x,yx,yx,y的异或值可以任意。
分析完之后就是数位dpdpdp裸题辣。
// Problem: Xor
// Contest: HDOJ
// URL: http://acm.hdu.edu.cn/showproblem.php?pid=6899
// Memory Limit: 524 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int a,b,k,w;
int A[210],B[210],K[210],W[210];
LL f[100][2][2][2][10][10];
//pos a<=A,b<=B,a^b<=W,x-y+k>=0,y-x+k>=0LL dp(int pos,int flag1,int flag2,int flag3,int k1,int k2) {if(pos==-1) return k1>=0&&k2>=0;if(k1<-1||k2<-1) return 0;k1=min(2,k1); k2=min(2,k2);if(f[pos][flag1][flag2][flag3][k1+1][k2+1]!=-1) return f[pos][flag1][flag2][flag3][k1+1][k2+1];int x=flag1? 1:A[pos];int y=flag2? 1:B[pos];int z=flag3? 1:W[pos];LL ans=0;for(int i=0;i<=x;i++) {//afor(int j=0;j<=y;j++) {//bif((i^j)>z) continue;ans+=dp(pos-1,flag1||i<x,flag2||j<y,flag3||((i^j)<z),k1*2+i-j+K[pos],k2*2+j-i+K[pos]);}}return f[pos][flag1][flag2][flag3][k1+1][k2+1]=ans;
}LL solve() {for(int i=30;i>=0;i--) {A[i]=a>>i&1;B[i]=b>>i&1;K[i]=k>>i&1;W[i]=w>>i&1;}return dp(30,0,0,0,0,0);
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);int _; scanf("%d",&_);while(_--) {memset(f,-1,sizeof(f));scanf("%d%d%d%d",&a,&b,&k,&w);printf("%lld\n",solve());}return 0;
}
/**/