LOJ6274 数字

先考虑另一个问题:在上下界限制下判断是否存在 (x,y) 满足 (x or y=v_1,x and y=v_2),设 (f(p,a,b,c,d)) 表示考虑到第 (p) 位和上下界限制是否合法。回到原问题,考虑 (DP)(DP),设 (g(p,S)) 表示考虑到第 (p) 位,(DP) 状态为 (S)(v_2) 个数,其中 (S) 是将上一个 (DP) 后四维中 (2^4) 种情况压起来,枚举 (v_2) 当前位的值即可转移。复杂度为 (O(2^{16}log T))

也可以直接数位 (DP),注意当前位与为 (0) 时有三种情况:(0 0,0 1,1 0),都加起来会算重,发现方案数小的情况一定是方案数大的情况的子集,于是取 (max) 转移即可。复杂度为 (O(2^4log T))

(DP)(DP)

#include<bits/stdc++.h>
#define maxn 62
#define maxm 65546
#define all 65535
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
	x=0;char c=getchar();bool flag=false;
	while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	if(flag)x=-x;
}
ll ans;
int w[maxn],Lx[maxn],Rx[maxn],Ly[maxn],Ry[maxn];
ll f[maxn][maxm];
int sta(int a,int b,int c,int d)
{
	return (a<<3)|(b<<2)|(c<<1)|d;
}
void work(int *a)
{
	ll v;
	int cnt=-1;
	read(v);
	while(v) a[++cnt]=v%2,v/=2;
}
int main()
{
	work(w),work(Lx),work(Rx),work(Ly),work(Ry),f[60][1<<sta(1,1,1,1)]=1;
	for(int p=59;p>=0;--p)
	{
		for(int s=0;s<=all;++s)
		{
			if(!f[p+1][s]) continue;
			for(int v=0;v<=1;++v)
			{
				int t=0;
				for(int a=0;a<=1;++a)
				{
					for(int b=0;b<=1;++b)
					{
						for(int c=0;c<=1;++c)
						{
							for(int d=0;d<=1;++d)
							{
								if(!((s>>sta(a,b,c,d))&1)) continue;
								for(int x=0;x<=1;++x)
								{
									for(int y=0;y<=1;++y)
									{
										if((x|y)!=w[p]||(x&y)!=v) continue;
										if(a&&x<Lx[p]) continue;
										if(b&&x>Rx[p]) continue;
										if(c&&y<Ly[p]) continue;
										if(d&&y>Ry[p]) continue;
										t|=1<<sta(a&(x==Lx[p]),b&(x==Rx[p]),c&(y==Ly[p]),d&(y==Ry[p]));
									}
								}
							}
						}
					}
				}
				f[p][t]+=f[p+1][s];
			}
		}
	}
	for(int i=1;i<=all;++i) ans+=f[0][i];
	printf("%lld",ans);
	return 0;
}

数位 (DP)

#include<bits/stdc++.h>
#define maxn 62
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
	x=0;char c=getchar();bool flag=false;
	while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	if(flag)x=-x;
}
int n;
int t[maxn],Lx[maxn],Rx[maxn],Ly[maxn],Ry[maxn];
ll f[maxn][2][2][2][2];
ll dp(int p,bool lx,bool rx,bool ly,bool ry)
{
	if(p==-1) return 1;
	if(f[p][lx][rx][ly][ry]!=-1) return f[p][lx][rx][ly][ry];
	ll v=0,mx=0;
	for(int i=0;i<4;++i)
	{
		int x=i&1,y=i>>1;
		if((x|y)!=t[p]) continue;
		if(lx&&x<Lx[p]) continue;
		if(rx&&x>Rx[p]) continue;
		if(ly&&y<Ly[p]) continue;
		if(ry&&y>Ry[p]) continue;
		bool t1=lx&(x==Lx[p]),t2=rx&(x==Rx[p]),t3=ly&(y==Ly[p]),t4=ry&(y==Ry[p]);
		if(x&y) v+=dp(p-1,t1,t2,t3,t4);
		else mx=max(mx,dp(p-1,t1,t2,t3,t4));
	}
	return f[p][lx][rx][ly][ry]=v+mx;
}
void work(int *a)
{
	ll v;
	int cnt=-1;
	read(v);
	while(v) a[++cnt]=v%2,v/=2;
	n=max(n,cnt);
}
int main()
{
	work(t),work(Lx),work(Rx),work(Ly),work(Ry);
	memset(f,-1,sizeof(f)),printf("%lld",dp(n,1,1,1,1));
	return 0;
}
原文地址:https://www.cnblogs.com/lhm-/p/14493913.html