首页 > 其他分享 >数列的异或和

数列的异或和

时间:2024-02-18 17:55:18浏览次数:19  
标签:数列 int lowbit add while 异或

  • 如果a ^ b=c,则c ^ a=b,c ^ b=a

  • a ^ b=b ^ a,(a ^ b) ^ c=a ^ (b ^ c)

  • a ^ b ^ b=a

  • 0 ^ a=a,a ^ a=0


数据:
n :数列长度
m :询问次数
a[] : 原数列
c[] :树状数组

函数 :

a[x]修改为y
void add(int x,int y)
{
    int i=x;
    while(i<=n)
    {
        c[i]^=a[x];  //还原,性质3
        c[i]^=y;
        i+=lowbit(i);
    }
    a[x]=y;
}

//另一种写法
void add(int x,int y)
{
    int w=a[x];
    while(x<=n)
    {
        c[x]^=w;  
        c[x]^=y;
        x+=lowbit(x);
    }  //因为x的值变了,所以a[x]=y写函数外面
}  //一定要记得修改a[x]!!!
x的前缀和
int gs(int x)
{
    int s=0;
    while(x)
    {
    	s^=c[x];
    	x-=lowbit(x);
    }
    return s;
}

初始化 : 全0

输入
for(int i=1;i<=n;++i)
{
    scanf("%d",&a[i]);
    for(int j=i;j>i-lowbit(i);--j)
    {
        c[i]^=a[j];  //性质4
    }
}

最终代码
#include<bits/stdc++.h>
using namespace std;

int n,m;
int a[114514],c[114514];

int lowbit(int x)
{
    return x&-x;
}

void add(int x,int y)
{
    int w=a[x];
    while(x<=n)
    {
        c[x]^=w;
        c[x]^=y;
        x+=lowbit(x);
    }
}

int gs(int x)
{
    int s=0;
    while(x)
    {
        s^=c[x];  //可见就是非常简单的把+换成^
        x-=lowbit(x);
    }
    return s;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&a[i]);
        for(int j=i;j>i-lowbit(i);--j)
        {
            c[i]^=a[j];
        }
    }
    for(int i=1;i<=m;++i)
    {
        int k,x,y;
        scanf("%d%d%d",&k,&x,&y);
        if(k==0)
        {
            add(x,y);
            a[x]=y;  //因为忘了写导致变成18+,望周知
        }
        if(k==1)
        {
            int ans=gs(y)^gs(x-1);
            printf("%d\n",ans);
        }
    }
}

标签:数列,int,lowbit,add,while,异或
From: https://www.cnblogs.com/miqa/p/18019644

相关文章

  • 选数异或
    引言题目链接:https://www.luogu.com.cn/problem/P8773思路令dp[i]表示以i结尾且前i个中满足\(a_j\oplusa_k=x\)的数对中左侧数最靠近右侧的位置。假设有\(a_1\oplusa_2=x\)且\(a_4\oplusa_6=x\)则dp[3]=1,dp[7]=4那么给出区间后只需要判断......
  • 异或和之和
    引言题目链接:https://www.luogu.com.cn/problem/P9236思路首先暴力的做法是求出其前缀异或数组sum,之后将其两两异或,结果相加,其时间复杂度为O(n^2)假设所有sum的二进制的第i位为a个1和b个0,那么根据异或的性质,1和1,0和0的异或结果为0,不影响结果。那么对结果......
  • P8248 简单数列 题解
    首先,圈重点:$1\len\le500$所有元素在$1\sim4$之间任意连续的连续子串不相同只要输出一种答案即可于是我们可以得到的是:由第一点和第二点可以看出此题可以写搜索解决。由第三点我们可以得到一种剪枝方式,就是如果目前数字放入后会产生相同的连续的连续子串。由第四点......
  • P2042 [NOI2005] 维护数列 题解
    题目链接:维护数列比较不好码的题,首先确保自己会一种文艺平衡树的书写,这点因人而异,比较推荐初学者学\(fhq\)平衡树,坑比较少,比较好码,写平衡树合并、持久化类的题时,也比较好写。注意到空间需求比较大,还涉及删除,我们的删除用各种树类数据结构中最常用的回收标记用于新的节点开辟。......
  • P1182 数列分段 Section II
    原题链接作为二分答案的入门题非常合适。很典型的二分答案。但是这题有一个坑点,left的值不能设为0这种确定的值,而是应该设为这个数组的最大值。这道题警示了我二分答案的一个重要前提:确定合理的二分区间。题解首先,判断单调性,对于一个最大值mid,如果能够满足check(),那么mid+1,mid+......
  • C语言解题 || 调整数列
    题目:有n个整数,使其前面各数顺序向后移m个位置,移出的数再从头移入,使得最后m个数变成前面m个数。例:设n为6,m为2,当n个数为{1,2,3,4,5,6},函数使之变为{5,6,1,2,3,4}编写一个函数move,实现以上功能,该函数的声明如下:voidmove(int*x,intn,intm)实现思想:拿出最后一个数,然后其他数字......
  • 简单的斐波那契数列通过chan实现生产者消费者模型
    1.实现斐波拉契数列写一个函数返回长度为n的斐波拉契slice数组funcfi(nint)[]int{ ifn<=0{ return[]int{} } fibs:=make([]int,n) fibs[0]=0 ifn>1{ fibs[1]=1 fori:=2;i<n;i++{ fibs[i]=fibs[i-1]+fibs[i-2] } } returnfibs}......
  • 牛牛的等差数列(树状数组,区间加等差数列、区间求和)
    https://ac.nowcoder.com/acm/contest/5157/C区间加等差数列,区间求和树状数组,二阶差分\(b_i=a_i-a_{i-1}\)\(c_i=b_i-b_{i-1}\)\[\sum_{i=1}^na_i=\sum_{i=1}^n\sum_{j=1}^ib_j=\sum_{i=1}^n\sum_{j=1}^i\sum_{k=1}^jc_k\\=\sum_{k=1}^nc_k\sum_{i,j}[k\......
  • 【题解】P5907 数列求和加强版 / P4948 数列求和
    本题解是对warzone的题解的补充。题意:求\[\sum_{i=1}^ni^ka^i\]普通版:\(k\leq2\times10^3\)。加强版:\(k\leq10^7\)。首先先考虑普通版。\[\begin{aligned}\sum_{i=1}^ni^ka^i&=\sum_{i=1}^na^i\sum_{j=0}^k{k\bracej}i^{\underline{j}}\\&=\sum_{j=0......
  • 洛谷P5907 数列求和加强版 / SPOJ MOON4
    题面描述求\[\sum_{i=1}^ni^ka^i\]对\(998244353\)取模的结果。\(O(k)\)做法为了推导方便,下令\(p=a^{-1}\)。即求\[\sum_{i=1}^n\frac{i^k}{p^i}\]我们裂项,即尝试寻找多项式\(f(x)\),使得\[\frac{x^k}{p^x}=\frac{f(x)}{p^{x-1}}-\frac{f(x+1)}{p^x}\]即\[x^k......