简单异或题小结(前缀+找规律)

简单异或题小结(前缀+找规律)


异或相关知识:


1、a⊕a=0;
2、a⊕b=b⊕a;
3、a⊕b⊕c=a⊕(b⊕c)=(a⊕b)⊕c;
4、d=a⊕b⊕c 可以推出a=d⊕b⊕c;
5、a⊕b⊕b=a(一个数异或另一个数两次等于原数);

PS:
c/c++中异或用 ^ 表示

开始还完全不了解异或这个概念,当看到几道题之后才知道异或这个概念,简单点说就是:转化为二进制,然后比较每位,如果相等则为0,不等则为1;

然后还需要注意的是,基本上异或问题都需要找规律,数据量大时,还需要用到前缀和

这里简单解释下前缀和:
就是:比如要求a,a+1,,,,b的和时,我们可以转化为用1,2,,,,,b的和减去1,2,,,,,a-1的和

下面就是两道例题:

A–Do You Like XOR? 题目链接


Description


Do you like XOR? Whatever your answer is, Backlight like XOR very much. Thus, he uses a XOR problem as an encryption algorithm, and apply it to his personal computer. The algorithm is as follow:
1.choose 3 integers a,b,c and a,b (1 <= a < b<= 10^18),c (1 <= c <= 10^18) .
2.calculate password for
pi = i ⊕ i ⊕ i⋯i(a total of c times)
在这里插入图片描述
here, ⊕ means XOR(exclusive OR).

One day, Backlight forget his password. But he remember the 3 integers he use to encrypt. Given the 3 integers, could you help him to calculate out his password?


Input


Input contains multiple test cases. Each test case consists of a pair of integers a, b and c , separated by a space, one pair of integers per line.


Output


For each test case, print a single integer on its own line denoting the password.


Sample Input


1 2 3
6 66 666


Sample Output


3
0


Hint


1⊕1⊕1=1,2⊕2⊕2=2,1⊕2=3

题解:这题开始真的是没想到,异或的概念都是到网上搜之后才知道,补题时寻求大佬,知道了一些,也就是前面所说的前缀+找规律(大佬的话:一般异或都是找规律),于是就开始暴力打表找规律。
当然,首先我们分析下这题:
当c为偶数时,结果显然是0
当c为奇数时,c-1就为偶数,于是我们可以把问题简化为a ^(a+1) ^ ^ ^ ^b;于是再运用前缀,把问题又可以转化为(1------b)的异或—(1-----a-1)的异或

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
    ll a=0;
    while(a<=100)
    {
        a++;
        ll sum=0;
        for(int i=1;i<=a;i++)
            sum^=i;
        printf("%lld\n",sum);
    }
    return 0;
}

通过这个找规律发现

ll fx(ll a)
{
    if(a%4==1)
        return 1;
    if(a%4==2)
        return a+1;
    if(a%4==3||a==0)
        return 0;
    if(a%4==0)
        return a;
}

于是最后AC代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll fx(ll x)
{
    if(x%4==1)
        return 1;
    if(x%4==2)
        return x+1;
    if(x%4==3||x==0)
        return 0;
    if(x%4==0)
        return x;
}
int main()
{
    ios::sync_with_stdio(false);
    ll a,b,c;
    while(~scanf("%lld%lld%lld",&a,&b,&c))
    {
        if(c%2==0)
        {
            printf("0\n");
        }
        else
        {
            ll num1=fx(a-1);
            ll num2=fx(b);
            ll num=num1^num2;
            printf("%lld\n",num);
        }
    }
    return 0;
}

B–many Sum 题目链接

在这里插入图片描述
在这里插入图片描述

题解:这题是牛客小白月赛的题,可以说是签到题,但是我没做出来(哭辽!!!)
这题数据量不大,可以直接暴力求解,当然备注写了,可以尝试数据量大的时候,看题解是说通过高维前缀和,我觉得应该也可以降维,然后在用前缀吧

暴力代码如下:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[2000010];
ll b[2000010];
int main()
{
    ll n,m;
    scanf("%lld%lld%lld",&n,&a[1],&m);
    for(int i=2;i<=n;i++)
    {
        a[i]=(a[i-1]+7*i)%m;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j+=i)
            b[j]+=a[i];
    }
    ll num=0;
    for(int i=1;i<=n;i++)
    {
        num^=b[i];
    }
    printf("%lld\n",num);
    return 0;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值