机房测试:race(trie)

Posted mowanying

tags:

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

题目:

技术图片

 

 分析:

先不考虑天数的限制,直接对每一个人建一颗trie。

对于每一个人来说,他的x的贡献来源于trie树上所有在他右边的点(都比他大)。

将每一个子树所有的叶子结点记为f,x^2=(f1+f2+……fx)^2

将右式拆开看:f i *f i + f i * f j *2(枚举i,j统计贡献,*2是因为 i 和 j 可以交换)

再加上天数的限制:每一个人的A[i]异或上天数 j,相当于trie树的形态发生改变了(01边交换)

技术图片

 

 对于1来说,又多了一部分贡献,也就是说,对于右子树来说,当且仅当交换1条边会产生贡献,而其它的m-1条边随便交换,所以是f i * f i *(2^(m-1))

对于i,j来说,当两条边被交换了,才会产生贡献,所以是 f i * f j *2 *(2^(m-2))

dfs一遍trie树,统计答案即可。

技术图片
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200005
#define ri register int
const ll mod = 1e9+7;
int go[N*30][2],siz[N*30],a[N],n,m,cnt=0;
ll ans=0;
void add(int x)
{
    int now=0;
    for(ri i=m-1;i>=0;--i){
        bool c=x&(1<<i); //这里的c一定要用bool,因为可能与出其它东西来,导致不是0和 1 
        if(!go[now][c]) go[now][c]=++cnt;
        now=go[now][c]; siz[now]++;
    }
}
void dfs(int x,ll sum,ll num)//num相当于是其它子树的siz 
{
    ll sz=siz[go[x][1]],tmp=0;
    tmp=sz*sz %mod *(1<<m-1) %mod; tmp=(tmp + sz*num %mod *(1<<m-1) %mod) %mod;
    if(go[x][0]) dfs(go[x][0],(sum+tmp) %mod, num+sz);
    
    sz=siz[go[x][0]],tmp=0;
    tmp=sz*sz %mod *(1<<m-1) %mod; tmp=(tmp + sz*num %mod *(1<<m-1) %mod) %mod;
    if(go[x][1]) dfs(go[x][1],(sum+tmp) %mod, num+sz);
    
    if(!go[x][0] && !go[x][1]) ans^=sum;//叶子节点 
}
int main()
{
    freopen("race.in", "r", stdin);
      freopen("race.out", "w", stdout);
    scanf("%d%d",&n,&m);
    for(ri i=1;i<=n;++i) scanf("%d",&a[i]),add(a[i]);
    dfs(0,0,0);
    printf("%lld
",ans);
}
/*
3 2
0 1 2
*/
View Code

 

 

 

以上是关于机房测试:race(trie)的主要内容,如果未能解决你的问题,请参考以下文章

机房测试1:big(贪心+Trie树)

Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题

Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题

如何在async.race函数中使用async.retry

慎用 -race 选项

为什么你不应该接受有 race 的代码