洛谷 P5614题解

吐槽:数据好像有点水,直接枚举到200可以得80 points。

另:我还是太弱了,比赛的时候只有90 points,#7死卡不过去,最后发现是没有判断 (z_1)(z_2) 的范围……


Subtask 1:

Method:

直接输出4,完。


Subtask 2:

Method:

直接暴力枚举 (x) , (y) , (z) ,判断是否满足一下关系即可:

[forall iinleft[1,n ight],s.t.left |a_i-x ight|igoplus left|b_i-y ight| igoplus left|c_i -z ight|=9 ]

时间复杂度:(O(nM^3))(nleq 5) ,可以忽略 )

可以通过 (60\%) 的数据。

Code

#include<bits/stdc++.h>
#define int long long 
#define Maxn 10
using namespace std;
inline void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int n,M;
int ans=0;
int a[Maxn],b[Maxn],c[Maxn];
void solve1()
{
	int flag=1;
	for(int x=1;x<=M;x++)
	{
		for(int y=1;y<=M;y++)
		{
			for(int z=1;z<=M;z++)
			{
				for(int i=1;i<=n;i++)
				{
					if((((abs(a[i]-x))^(abs(b[i]-y)))^(abs(c[i]-z)))!=9)
					{
						flag=0;
						break;
					}
				}
				if(flag==1)
				{
					ans++;
				}else
				{
					flag=1;
				}
			} 
		}
	}
	printf("%lld
",ans);
	return ;	
} 
signed main()
{
	read(n),read(M);
	for(int i=1;i<=n;i++)
	{
		read(a[i]);
		read(b[i]);
		read(c[i]);
	}
	ans=0;
	if(M<=200)
	{
		solve1();
		return 0;
	}
}

Subtask 3:

**Method **:

考虑优化枚举。若满足一下的性质:

[Aigoplus Bigoplus C=D ]

则显然可以得到:

[egin{equation} egin{aligned} & Aigoplus B igoplus D\ & =A igoplus B igoplus left(Aigoplus Bigoplus C ight) \ & = left[left(A igoplus B ight) igoplus left(Aigoplus B ight) ight]igoplus C\ & ecause x igoplus x=0,0igoplus x=x\ & herefore A igoplus B igoplus D =C end{aligned} end{equation} ]

故只需要枚举 (x)(y) ,则:

[egin{equation} egin{aligned} & left|c_1-z ight|=left|a_1-x ight|igoplus left|b_1-y ight| igoplus 9 end{aligned} end{equation} ]

我们设

[C=left|a_1-x ight|igoplus left|b_1-y ight| igoplus 9 ]

则:

[z_1=c_1-C,z_2=c_1+C ]

最后只需要判断一下 (z_1)(z_2) 是否满足以下性质即可:

[forall iin left[2,n ight],s.t.left |a_i-x ight|igoplus left|b_i-y ight| igoplus left|c_i -z_j ight|=9 ext{且}z_j in [1,M]\ (jin {1,2}) ]

时间复杂度:(O(nM^2))(nleq 5) ,可以忽略 )

Code:

#include<bits/stdc++.h>
#define int long long 
#define Maxn 10
using namespace std;
inline void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int n,M;
int ans=0;
int a[Maxn],b[Maxn],c[Maxn];
map<int,int>mp;
void solve1()
{
	int flag=1;
	for(int x=1;x<=M;x++)
	{
		for(int y=1;y<=M;y++)
		{
			for(int z=1;z<=M;z++)
			{
				for(int i=1;i<=n;i++)
				{
					if((((abs(a[i]-x))^(abs(b[i]-y)))^(abs(c[i]-z)))!=9)
					{
						flag=0;
						break;
					}
				}
				if(flag==1)
				{
					ans++;
				}else
				{
					flag=1;
				}
			} 
		}
	}
	printf("%lld
",ans);
	return ;	
} 
void solve2()
{
	int flag1=1,flag2=1;
	for(int x=1;x<=M;x++)
	{
		for(int y=1;y<=M;y++)
		{
			mp.clear();
			int tmp=(((abs(a[1]-x))^(abs(b[1]-y)))^9);
			int zkkk=c[1]-tmp;
			int zwww=c[1]+tmp;
			if(zkkk>=1&&zkkk<=M)
			{
				for(int i=2;i<=n;i++)
				{
					if((((abs(a[i]-x))^(abs(b[i]-y)))^(abs(c[i]-zkkk)))!=9)
					{
						flag1=0;
						break;
					}
				}
				if(flag1==1&&mp.find(zkkk)==mp.end())
				{
					ans++;
					mp[zkkk]=1;
				}else
				{
					flag1=1;
				}
			}else
			{
				flag1=1;
			}
			if(zwww>=1&&zwww<=M)
			{
				for(int i=2;i<=n;i++)
				{
					if((((abs(a[i]-x))^(abs(b[i]-y)))^(abs(c[i]-zwww)))!=9)
					{
						flag2=0;
						break;
					}
				}
				if(flag2==1&&mp.find(zwww)==mp.end())
				{
					ans++;
				}else
				{
					flag2=1;
				}
			}else
			{
				flag2=1;
			}
		}	
	}
	printf("%lld
",ans);
	return ;
}
signed main()
{
	read(n),read(M);
	for(int i=1;i<=n;i++)
	{
		read(a[i]);
		read(b[i]);
		read(c[i]);
	}
	ans=0;
	if(M<=200)
	{
		solve1();
		return 0;
	}
	else 
	{
		solve2();
		return 0;
	}
}
原文地址:https://www.cnblogs.com/nth-element/p/11788448.html