首页 > 其他分享 >[CF1616H] - Keep XOR Low 的题解

[CF1616H] - Keep XOR Low 的题解

时间:2024-10-19 10:43:34浏览次数:1  
标签:XOR rs int 题解 Low siz mod define ls

一道比较神奇的题目,状态显得比较扯淡,但是就是能过!

先建立出 trie 树,设 \(dp_u\) 表示以 \(u\) 为根的子树内的答案。

但我们发现,若 \(x\) 的当前位为 \(1\),那么问题就没法根据他的左右子树求解了,怎么办呢。

考虑一个很扯淡的状态,设 \(dp_{u,v}\) 表示考虑了 \(u,v\) 为根的子树,他的答案。

再设一下 \(siz_u\) 表示以 \(u\) 为根的子树实际上加入过几个数。

一开始我们就还说搞 \(dp_u\),但遇到了 \(x\) 当前位数为 0 的情况,我们就递归进入的 \(dp_{ls_u,rs_u}\)。

并且这样子的话,有一个很好的性质,就是对于 \(dp_{u,v}(u\neq v)\),\(u,v\) 内是可以互相随便选的!

考虑一下 \(dp_{u,v}\) 的转移。

  1. 若 \(x\) 当前位为 \(1\),那么相互之间有限制的只有 \((ls_u,rs_v),(rs_v,ls_u)\),我们递归求解这两个,然后乘起来即可,注意还要保留只选的情况。

  2. 若 \(x\) 当前位为 \(0\),那么由于上面的那个性质,\(u\) 的左右儿子是可以随便搭配的,\(v\) 的也是同理,而若想要交叉一下,那么只有 \((ls_u,ls_v),(rs_u,rs_v)\) 可以,递归求解即可。

然后对于叶子结点,显然是可以随便选的。

发现我们每次 \(dp\) 实际上就是进入他的子树,所以时间为 \(\mathcal{O}(n\log V)\)。

#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define p_b push_back
#define m_p make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define ls(x) tree[x][0]
#define rs(x) tree[x][1]
#define mid ((l+r)>>1)
#define gcd __gcd
#define lowbit(x) (x&(-x))
using namespace std;
int rd(){
    int x=0,f=1; char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if (ch=='-') f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
    return x*f;
}
void write(int x){
    if(x>9) write(x/10);
    putchar('0'+x%10);
}
const int N=2e5+5,mod=998244353;

int tot=1,n,x;
int tree[N*30][2],siz[N*30],pw[N];
void insert(int val){
    int u=1;siz[u]++;
    for(int i=29;i>=0;i--){
        int c=((val>>i)&1ll);
        if(!tree[u][c]) tree[u][c]=++tot;
        u=tree[u][c],siz[u]++;
    }
}
void add(int &x,int y){
    x+=y;
    if(x>=mod) x-=mod;
}
int solve(int u,int v,int d){
    if(!u||!v) return pw[siz[u]+siz[v]];
    if(u==v){
        if(d<0) return pw[siz[u]];
        if((x>>d)&1ll) return solve(ls(u),rs(u),d-1);
        else return (solve(ls(u),ls(u),d-1)+solve(rs(u),rs(u),d-1))%mod;
    }
    else{
        if(d<0) return pw[siz[u]+siz[v]];
        if((x>>d)&1ll) return ((solve(ls(u),rs(v),d-1)+1)*(solve(rs(u),ls(v),d-1)+1)%mod-1+mod)%mod;
        else{
            int ans=(solve(ls(u),ls(v),d-1)+solve(rs(u),rs(v),d-1))%mod;
            add(ans,pw[siz[ls(u)]]*pw[siz[rs(u)]]%mod);
            add(ans,pw[siz[ls(v)]]*pw[siz[rs(v)]]%mod);
            return ans;
        }
    }
}

signed main(){
    n=rd();x=rd();
    for(int i=1;i<=n;i++) insert(rd());
    pw[0]=1;
    for(int i=1;i<=n;i++) pw[i]=(pw[i-1]+pw[i-1])%mod;
    for(int i=0;i<=n;i++) add(pw[i],mod-1);
    printf("%lld\n",solve(1,1,29)%mod);
    return 0;
}

标签:XOR,rs,int,题解,Low,siz,mod,define,ls
From: https://www.cnblogs.com/123456xwd/p/18475586

相关文章

  • 牛客练习赛130-A题题解
    牛客练习赛130-A题题解题目描述如下:给定两个整数x,y,jackle希望把x变成y。他每次可以进行如下两种操作之一:选择任意一个整数z,令x=x&z。选择任意一个整数z,令x=x|z。请问最少操作几次可以把x变成y。输入描述:本题有多组测试数据。第一行输入1个正整数T(1≤T......
  • [ABC134F] Permutation Oddness 题解
    T5[ABC134F]PermutationOddness很无敌的一道题。(好像是我第一次用无敌这个词把\(p_i\)和\(i\)的对应关系转化为球和盒子的配对问题,则原式中的绝对值顺利成章地就变成类似距离的一个东西。那么设\(f_{i,j,k}\)表示前\(i\)个球和盒子(注意球和盒子是一起考虑的,所以\(i......
  • [ARC185D] Random Walk on Tree 题解
    一个很套路的做法。思路题目要求走完整个树的时间,这并不好算,容易想到min-max容斥。依据min-max容斥,我们可以轻松把它转化成第一次走到所有子集的时间。考虑在这道题中,有什么特殊的。第一,任何包含根节点的子集答案都是零。第二,由于我们只关心第一次走到的点的时间,因此假......
  • ZZJC新生训练赛第五场题解
    A题思路题目要求构造一个相邻两项互质的长度为n的序列。可以直接选择输出从1到n的自然数序列,因为相邻的自然数总是互质的。题目有多个测试用例,因此需要逐个处理输入,并输出对应结果。代码#include<bits/stdc++.h>usingnamespacestd;intmain(){ios::sync_wit......
  • 题解:[YNOI2019] 游戏
    ProblemLink[YNOI2019]游戏题外话第一眼,由乃?不打不打。第二眼,欸noi三个字母怎么是大写(才发现是云南省选)。题意题意简洁,不再赘述。Solution一眼看出概率dp,但如何似乎没思路?开始公式做题:设置状态+推转移式。\(Q1\):怎么设置状态?首先,思考一个问题:第\(k\)个人该怎么“......
  • 异常问题解决
    异常:java程序编译或运行过程中出现的问题Throwable:Error:表示非常严重的问题,自己无法解决的问题Exception:除了RuntimeException其它异常【编译时期异常】:一般指的是异常尚未处理就编译了RuntimeException【运行时期异......
  • PTA L1系列题解(C语言)(L1_081 -- L1_088)
    L1-081今天我要赢题目内容:2018年我们曾经出过一题,是输出“2018我们要赢”。今年是2022年,你要输出的句子变成了“我要赢!就在今天!”然后以比赛当天的日期落款。输入格式:本题没有输入。输出格式:输出分2行。在第一行中输出I'mgonnawin!Today!,在第二行中用年年年......
  • 数据库性能调优:定位Slow SQL!
    定位慢SQL(SlowSQL)是数据库性能调优中的一个重要任务,目的是找到和优化那些执行时间较长的SQL查询。以下是常用的定位慢SQL的方法和步骤:1.使用数据库自带工具大多数数据库管理系统(DBMS)提供了内置的工具和视图来帮助定位慢SQL。以下是一些主要数据库的常用工具:MySQL慢......
  • P1955 程序自动分析 题解
    P1955程序自动分析一道并查集的裸题,并查集存储传递性,后判断。主题思路十分简单,重点在于离散化与离线的处理。离散化,为什么会想到离散化呢,观察数据范围\(1<i,j<{10}^9\),数据范围过大,导致数组不可能开到\(1e9\)但是\(1<n<1e5\)考虑到每次输入只有两个数,若每个数都两两不同,......
  • 【题解】[Codechef] Beautiful Permutation
    传送门以此纪念我场切的dp。这种计数的类型一看就很dp的样子。考场上一开始设的dp状态是\(dp_{i,j,k_1,k_2,0/1}\)表示将前\(i\)个数分为\(j\)段,放了\(k_1\)个偶数,\(k_2\)个奇数,当前段为偶数段或奇数段的方案数。考虑如何转移,记\(cnt_0\)表示序列中可填入的偶数......