SCAU 10678 神奇的异或

10678 神奇的异或

时间限制:1000MS  内存限制:65535K

题型: 编程题   语言: 无限制

Description

    在现在这个信息时代,数据是很重要的东西哦~
    很多时候,一条关键的数据(情报、信息)是可以价值千金的。
所以,现代也出现了很多数据校验技术来确保数据的正确性。

    以下是一种校验算法:
    K字节称为一个校验段,校验段的的K个字节的异或结果等于0时,校验段合法。

输入格式

有若干组输入。以EOF为结束。
每组输入第一行是数据长度n,和查询次数qn,以空格隔开。
接下来一行工n*2个字符,是十六进制(大写)表示的n个字节的数据。
然后有qn行输入,每行对应一个查询。
每行查询有pos和k,表示查询从pos位置开始的k个字节的数据能否通过校验。
2<=n<=50000,1<=qn<=20000, 1<=k<=n, 0<=pos<=n-k

输出格式

对于每组数据,输出一行,输出通过检验的次数。

输入样例

10 6
F132274D3CFB0A95009F
1 7
2 7
1 8
1 8
0 9
0 7

输出样例

3

来源

by 200930740513 

作者

admin

解题思路

之所以神奇,是因为这题要用到异或再异或之后回到本身这个神奇的性质,题目每一个qn基本都是检验随机一段的合法性,数据量大如果一个一个去异或肯定会超时,采取的办法是记录每一个字节所在位置存储此字节跟前面所有字节异或后的结果(其实只要异或前面字节位置存储的结果),这点在输入字节的时候就需要进行计算。有n个字节就用数组存储n个异或结果,最后一个位置存储的就是全部字节异或的结果。现在如果要求pos位置后面k个字节异或的结果进行检测,那么根据之前存储的总的异或后得结果,用存储的数组下标【k+pos-1】跟【pos-1】下标再一次进行异或就能得到结果,从而判断是否为零

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define SIZE 16
 5 #define MAXN 50000*2+10
 6 using namespace std;
 7 
 8 int hexor[SIZE][SIZE];
 9 int store[MAXN];
10 int n, qn;
11 
12 void init()
13 {
14     for(int i=0; i<SIZE; ++i)
15         for(int j=i; j<SIZE; ++j)
16             hexor[i][j] = hexor[j][i]= i^j;
17 }
18 
19 int main()
20 {
21     char first, second;
22     int str, stp;
23     init();
24     while(scanf("%d%d", &n, &qn) != EOF)
25     {
26         getchar();
27         for(int i=0; i<n; ++i)
28         {
29             scanf("%c%c", &first, &second);
30             str = first >= '0' && first <= '9' ? (first - '0') : (first - 'A' + 10);
31             stp = second >= '0' && second <= '9' ? (second - '0') : (second - 'A' + 10);
32             if(!i) store[i] = str*16+stp;
33             else store[i] = hexor[store[i-1]/16][str]*16 + hexor[store[i-1]%16][stp];
34         }
35         int sum = 0, pos, k, temp;
36         for(int t=1; t<=qn; ++t)
37         {
38             scanf("%d%d", &pos, &k);
39             if(!pos && !store[k+pos-1]) sum++;
40             //这里不能这样写: store[k+pos-1]^store[pos-1] == 0
41             else if((temp = store[k+pos-1]^store[pos-1]) == 0) sum++; 
42         }
43         printf("%d\n", sum);
44     }
45     return 0;
46 }

 

转载于:https://www.cnblogs.com/liaoguifa/p/3188303.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值