luogu4443 coci 2017 Dajave

Posted chdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu4443 coci 2017 Dajave相关的知识,希望对你有一定的参考价值。

题目

给出一个长度为2^M的排列,元素分别是0, 1, 2, ... , 2^M -1。 选择其中某个非空连续子序列,然后允许交换这个排列中某两个不同的数,然后使得这个连续子序列的所有数的按位异或(bitwise XOR)的结果恰好等于2^M-1 求:有多少个连续子序列满足上述条件。

Hint

(mleq20)

简化题意 设a[i]表示0~i的(b_i)异或和.求有多少个l,r满足a[l-1]^a[r]==maxx/a[l-1]^a[r]^b[A]^b[B]==maxx 其中maxx=2^M-1;

当然A和B一个在l~r之中一个不在 都在或都不在可以转换为上述情况。

左边很好求出 直接上Trie树即可,关键是右边。先考虑暴力的想法 设C=a[l-1]^a[r] C^maxx=b[A]^b[B].

C^maxx此时为定值 对于l~r之中每一个(b_i,iin (l,r)) 都必然存在且只存在一个位置K满足(b_i)^(b_K)=C^maxx;

所以我们只需要找到一个位置i 使得位置K在(l,r)的外 即可判定l 和 r是合法的。

这个东西我们发现可以(n^3)的暴力了 发现我们优化不了这个东西。不妨补集转换。

求出 有多少l r是不合法的 即求出除了不满足第一种情况外也不满足第二种情况。

对于第二种情况 对于每一个位置i 其位置K都在集合之内。

由于每个i都仅对应一个K 所以当区间为奇数的时候是必然满足条件的。

讨论 区间为偶数的时候 匹配后奇数对一定不存在 如 2 6 他们如果可以成功配对 且配对数字为w C^maxx=w 且C=w maxx=0 故这种情况不存在。

考虑区间为4的倍数且两两配对的情况 可以发现此时w为定值maxx 所以对于每一个i来说我们都已经知道其配对位置在哪了。

问题也就转换成如何快速求出一个序列 每个数字都出现了两次 要求复杂度O(1) 本着异或的思想我们可以取异或前缀和判断 但是这样会误判

所以有一个非常经典的做法 给每个值都随便赋值 然后 再异或可以大大减小这种碰撞概率(双模双hash 这样稳一点。

关于这道题的线段树做法 我不会怎么扫描线能把这个东西扫出来 还是使用hash吧 舒服一点。。

const int MAXN=1100000;
int n,m;
int a[MAXN],pos[MAXN];
int w[MAXN][2];
map<pair<int,int>,int>H[4];
int main()
{
    freopen("1.in","r",stdin);
    srand(time(0));
    get(m);n=(1<<m)-1;
    if(m==1){puts("2");return 0;}
    for(int i=1;i<=n+1;++i)get(a[i]),pos[a[i]]=i;
    for(int i=0;i<=n/2;++i)
    {
        w[pos[i^n]][0]=w[pos[i]][0]=rand()<<15|rand();
        w[pos[i^n]][1]=w[pos[i]][1]=rand()<<15|rand();
    }
    ll ans=(ll)(n+1)*(n+2)/2;
    H[0][mk(0,0)]=1;
    for(int i=1;i<=n+1;++i)
    {
        w[i][0]^=w[i-1][0];
        w[i][1]^=w[i-1][1];
        ans-=H[i%4][mk(w[i][0],w[i][1])];
        ++H[i%4][mk(w[i][0],w[i][1])];
    }
    printf("%lld
",ans);
    return 0;
}

以上是关于luogu4443 coci 2017 Dajave的主要内容,如果未能解决你的问题,请参考以下文章

luogu P5052 [COCI2017-2018#7] Go

[Luogu5181][COCI2009]GENIJALAC

Luogu5307 [COCI2019] Mobitel 数论分块递推

Luogu_4329 [COCI2006-2007#1] Bond

luogu P5306 [COCI2019] Transport

Luogu4433:[COCI2009-2010#1] ALADIN(类欧几里德算法)