Codeforces Round #757 (Div. 2) C. Divan and bitwise operations

博客探讨了一种数学问题,即给定数组元素个数和多个区间异或和,如何求所有子序列的异或和。文章指出,由于或运算的特性,无法直接还原原始数组,但可以通过考虑每一位上的数字出现次数来求解。文章提供了一个结论,对于某一位,如果区间内没有出现,它不会影响答案;若出现,则根据出现次数的奇偶性确定其对答案的贡献。通过位运算和二项式定理,可以高效计算答案。博主分享了实现代码,并证明了这一结论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个题实在太巧了

给你一个数组的元素个数,给出若干个区间的或和,问任意一个合法的原序列的所有子序列的区间异或和是多少

  • 或的特点是二进制位只要有一个1,结果的对应位置就是1,可以想一下,给出这若干个区间信息,想要还原数组基本不太可能,而且就算是还原出了原来的数组,我们又怎么算这所有子序列的异或和呢?这个思路不靠谱

  • 单独考虑某一位上的数字,如果这个数字在给出的区间范围内没有体现,那它就不会出现在答案中;否则要考虑子序列中该位对应的数出现奇数次和偶数次这两种情况,如果是偶数次,它对答案的贡献也是0;如果是奇数次,那么这个结论是包含第iii位的子序列个数是2n−12^{n-1}2n1

  • 知道这个结论以后,因为每个位之间是并列关系,所以我们分别考虑每一位然后加一起就是答案,比如说现在给我们l,r,xl,r,xl,r,x,假设都是对于某一位的,举一些例子a1∣a2∣a3=x1a3∣a4∣a5∣a6=x2a8∣a9∣a10=x3a_1|a_2|a_3=x_1 \\a_3|a_4|a_5|a_6=x_2\\a_8|a_9|a_{10}=x_3a1a2a3=x1a3a4a5a6=x2a8a9a10=x3

  • 上面例子随便举的,那我们合并一下,就可以得到a1∣a2∣a3∣a4∣a5∣a6∣a8∣a9∣a10=x1∣x2∣x3a_1|a_2|a_3|a_4|a_5|a_6|a_8|a_9|a_{10}=x_1|x_2|x_3a1a2a3a4a5a6a8a9a10=x1x2x3,那么我们给这些数的这一位都标上一样的数字,如果右侧是0,那么全标0,否则全标1,那么这里面0的情况对答案的贡献是0,不用管,所以答案就是x×2n−1x\times2^{n-1}x×2n1

  • 感觉他们能秒了这个题肯定是早就知道这个结论

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll MOD = 1e9 + 7;
ll fastpow(ll base, ll power, ll mod){
    ll ans = 1;
    while(power){
        if(power & 1) ans = ans * base % mod;
        base = base * base % mod;
        power >>= 1;
    }
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >> t;
    while(t--){
        ll l, r, x;
        int n, m;
        cin >> n >> m;
        ll ans = 0;
        for(int i=0;i<m;i++){
            cin >> l >> r >> x;
            ans |= x;
        }
        cout << ans * fastpow(2ll, n - 1, MOD) % MOD << '\n';
    }
    return 0;
}
  • 按照官方题解思路对此结论进行证明,把第iii位为0的标号划分为集合AAA,把第iii位为1的标号划分为集合BBB, 因为x⊕0=xx\oplus0=xx0=x,所以无论如何选择AAA中元素都不会影响答案,所以这一部分数量是2∣A∣2^{|A|}2A;对于集合BBB,因为都是1,所以只需要考虑异或出来是1的组合即可,这部分的数量为(∣B∣1)+(∣B∣3)+...+(∣B∣∣B∣−k)=2∣B∣−1\begin{pmatrix} |B| \\ 1 \end{pmatrix}+\begin{pmatrix} |B|\\3\end{pmatrix}+...+\begin{pmatrix} |B|\\|B|-k\end{pmatrix}=2^{|B|-1}(B1)+(B3)+...+(BBk)=2B1,当BBB为偶数时kkk111,当BBB为奇数时,kkk000
  • AAABBB组合在一起,答案就是2∣A∣×2∣B∣−1=2n−12^{|A|}\times2^{|B|-1}=2^{n-1}2A×2B1=2n1

备注 (1−x)n=Cn0(−1)0x0+Cn1(−1)1x1+...+Cnn(−1)nxn(1-x)^n=C_n^0(-1)^0x^0+C_n^1(-1)^1x^1+...+C_n^n(-1)^nx^n(1x)n=Cn0(1)0x0+Cn1(1)1x1+...+Cnn(1)nxn
x=1x=1x=1得到
Cn0+Cn2+...+Cnn−(n&1)=Cn1+Cn3+...+Cnn−(!(n&1))C_n^0+C_n^2+...+C_n^{n-(n\&1)}=C_n^1+C_n^3+...+C_n^{n-(!(n\&1))}Cn0+Cn2+...+Cnn(n&1)=Cn1+Cn3+...+Cnn(!(n&1))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值