【找规律】【一套NOIP膜你赛】膜拜azui

问题描述

一天,小 A 给了 J·G 一道水题,J·G 一眼秒了,现在 J·G 想考考你们:
小 A 有 N 个灯,排成了一列,现在小 A 给出来一个叫做 azui 的奇葩操作,我们把开着的灯看作数字 1,把关着的灯看作数字 0,定义 0 azui 0 = 1,0 azui 1 = 0,1 azui 1 = 1, 1 azui 0 = 0。现在小 A 有 N 个问题 azui(l,r),表示询问从左往右的第 l 个灯向右一个一个 azui 到第 r 个灯的结果是什么。

输入

第1 行一个整数 N 表示序列的长度。
第2 行 N 个整数 Ai,每个数不是 0 就是 1,表示灯是关的还是开的。
第3 行一个整数 M 表示询问的个数。
第4~M+3 行,每行两个整数 l 和 r,表示询问 azui(l,r)。

输出

共 M 行,第 i 行回答第 i 个询问。

样例输入

5
1 0 1 0 1
5
2 3
3 4
4 5
1 3
1 4

样例输出

0
0
0
0
1

数据范围

对于 30%的数据,N和 M <= 5000
对于 80%的数据,N和 M <= 500000
对于 100%的数据,N和 M <= 1000000

分析

这个azui运算就是同或。相同的就是1,不同的就是0.即

bool azui(bool a,bool b){return a==b;}

我们可以枚举出同或的规律:

Example Answer
0 0 1
0 1 0
1 0 0
1 1 1
0 0 0 0
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 1
1 0 1 0
1 1 0 0
1 1 1 1

然后我发现同或似乎与数的排列方式无关,与数组中的0的个数有关。也可以发现同或的结合律 (ab)c=a(bc) 你发现这个东西,其实是可减的,求一个前缀和然后减一下,求出来了。

源代码

#include
#include
#include
using namespace std;
int n,m,l,r;
const int N=1000001;
bool azui(int x,int y){return x==y;}
bool a[N];
void get(int &a){
    a=0;char ch=getchar();
    while(ch<'0'||ch>'9')   ch=getchar();
    while(ch>='0'&&ch<='9'){a=a*10+ch-'0';ch=getchar();}
}
void get(bool &a){
    char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();
    if(ch=='0') a=0;
    else a=1;
}
int main()
{
    get(n);
    for(int i=1;i<=n;i++)
        get(a[i]);
    for(int i=2;i<=n;i++)
        a[i]=azui(a[i],a[i-1]);
    get(m);
    while(m--){
        get(l);get(r);
        printf("%d\n",l==1?a[r]:azui(a[l-1],a[r]));
    }
}

你可能感兴趣的:(#,C++,#,School,OJ,#,位运算)