trie+dfs+贪心 big

题面去内网找

这是这一组题里最好的一道。这个处理相当于把原数<<1后,如果第n位上有值,补到第0位上。其实硬算就行。。如果对手在第i次操作后进行处理,相当于把a1~i异或后左移了一次,而对于取不同的i,共会产生m+1种不同的结果,只要去找初始选取的数值,^每一种结果去比较。
但我们发现,最多有2^30种不同的初始值。。。但是,对于确定的m+1种结果,我们可以确定每一位异或0还是1使得结果最大,而且对手会根据我选的更改答案。。。那么可以对m+1种结果造一颗trie树,然后从高位开始贪心。如果子节点同时有0和1,那么选哪一个都会被对手改成对答案贡献为0,但如果只有其中一个,对手就没有更改的选择,那么一定会对答案产生贡献。依次逐位贪心,dfs修改答案即可。

#pragma GCC optimize("O3")
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100005
#define ll long long
using namespace std;
int read()
{
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
    while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}
    return sum*f;
}
ll n,m,a[N],xp[35],s[N],sum[N],ans1,ans2;
struct trie
{
    trie *ch[2];int end;
    trie(){end=0;memset(ch,0,sizeof(ch));}
}*root=new trie();
ll get(ll x)
{
    if(x&xp[n-1])return(x<<1)&(xp[n]-1)|1;
    return (x<<1)&(xp[n]-1);
}
void insert(ll x)
{
    trie *now=root;
    for(int i=n-1;i>=0;i--)
    {
        bool k=x&xp[i];
        if(!now->ch[k])now->ch[k]=new trie();
        now=now->ch[k];
    }
    now->end=1;
}
void dfs(trie* x,int k,ll sum)
{
    if(!k)
    {
        if(sum>ans1){ans1=sum,ans2=0;}
        if(sum==ans1)ans2++;
        return;
    }
    if(x->ch[0]&&x->ch[1])
    {
        dfs(x->ch[0],k-1,sum);
        dfs(x->ch[1],k-1,sum);
    }
    else
    {
        if(x->ch[0])
            dfs(x->ch[0],k-1,sum+xp[k-1]);
        else
            dfs(x->ch[1],k-1,sum+xp[k-1]);
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=m;i++)a[i]=read();
    xp[0]=1;for(int i=1;i<=n;i++)xp[i]=xp[i-1]*2ll;
    sum[1]=a[1];for(int j=2;j<=m;j++)sum[j]=sum[j-1]^a[j];
    for(int i=0;i<=m;i++)
    {
        ll x=get(sum[i])^sum[m]^sum[i];
        insert(x);
    }
    dfs(root,n,0);
    printf("%lld\n%lld",ans1,ans2);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值