[JZOJ3342] 求生之路

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hzj1054689699/article/details/83109751

Description

历经千辛万苦,pty终于打开了金字塔的锁。稍稍适应了外面刺眼的光线,pty抬头望去,眼前竟是一条不见尽头的狭长通道。这时候背后响起了奇怪的窸窣声,原来是金字塔内绿眼黑身的怪物追了过来。Pty来不及多想,便拼命往前奔去。通道狭窄又曲折,时不时还有断裂,不过Pty凭借TempleRun练成的娴熟技巧轻松通过。眼看着离怪物们越来越远时,一棵参天大树突然耸立在了道路中央,大树摆了摆身子,用苍老的声音说道:“孩子,我是远古的守护神。你打扰了这里的清净,想要从我这里通过,必须要解决一道来自远古的问题。”
现在有n堆石子,每堆石子分别有ai个,问有多少个d使得下式成立:
( a 1 d ) x o r ( a 2 d ) x o r . . . x o r ( a n d ) = 0 , 0 d < a i (a_1-d)xor(a_2-d)xor...xor(a_n-d)=0,0\leq d<a_i
守护神出的题自然是神题了,同是身为神的你可以解决么?
n 200000 , a i 1 0 18 n\leq200000,a_i\leq10^{18}

Solution

由于每一位异或是独立的,我们明显应该考虑数位DP。

对于每一位分0/1讨论,再考虑上退位的情况。

但摆在眼前的困难是,我们既不能记已经减去的d为状态(状态数是ai的),也不能记有哪些是需要退位的(状态数为 2 n 2^n

但有一个性质非常显然而又容易忽视。
假设我们当前做到第i位( 2 i 2^i ),有j个数需要退位,那么这j个数一定是所有数中 2 i 2^i 位到 2 0 2^0 位最小的j个(只考虑末i位,减去同样的d,更小的一定更有可能退位)

那么对于每一位,我们都预处理只考虑末这么多位排序的结果。
状态就可以精简成 n log a n\log a 的:
F [ i ] [ j ] F[i][j] 表示当前做到 2 i 2^i 这一位,有j个数需要退位。

此时只需要分0/1讨论一下,统计一下1的个数是否为偶数即可。
复杂度 O ( n log n ) O(n\log n)

Code

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 200005
#define LL long long
using namespace std;
int n,a1[62][N],cnt[62];
LL f[62][N],a[N],cf[61];
int main()
{
	cin>>n;
	fo(i,1,n) scanf("%lld",&a[i]),a1[0][i]=i;
	cf[0]=1;
	fo(i,1,60) cf[i]=cf[i-1]*(LL)2;
	fo(j,1,60)//方便起见这里的j=0实际上是第-1位,j=1才是2^0
	{
		int t0=0;
		fo(i,1,n) if(!(a[i]&cf[j-1])) t0++;
		fo(i,1,n) 
		{
			if(a[a1[j-1][i]]&cf[j-1]) a1[j][++t0]=a1[j-1][i];
			else a1[j][++cnt[j]]=a1[j-1][i];
		}
	}
	//上面部分为排序,记录cnt[j]表示2^(j-1)这一位为0的a的个数
	f[0][0]=1;
	fo(j,0,59)
	{
		int w=0,w1=0;
		fo(i,0,n)
		{
			if(i)
			{
				if(a[a1[j][i]]&cf[j]) w1++;
				else w++;
			}
			if((n-cnt[j+1]-w1+w)%2==0) f[j+1][w]+=f[j][i];//讨论2^j这一位选0
			if((w1+cnt[j+1]-w)%2==0) f[j+1][cnt[j+1]+w1]+=f[j][i];//讨论2^j这一位选1
		}
	}
	LL mi=1e18,v=0;
	fo(i,1,n) mi=min(mi,a[i]);
	fo(i,1,n) v^=(a[i]-mi);
	if(v==0) v=-1;
	else v=0;
	printf("%lld\n",f[60][0]+v);
}

猜你喜欢

转载自blog.csdn.net/hzj1054689699/article/details/83109751
今日推荐