2018 FJUT ACM校赛 B题 第二集:以后我就叫你小蛤了

第二集:以后我就叫你小蛤了

TimeLimit:1000MS  MemoryLimit:128MB
64-bit integer IO format:%lld
 
Problem Description

"小蛤啊,对了以后我就叫你小蛤了,你给的题完全没有难度啊"

"哼,你别得意,让你碰巧做出来了而已,接下来这题你绝对不可能做出来的,你要是做出来了balabalabala...."

"行了行了,快说题目吧,我时间宝贵啊!" 小A心急如焚,想尽快知道小C的消息

"请听题:

给n个正整数a1,a2,a3,……,an,求所有子区间异或和的异或和。比如{2,4,6}的子区间有{{2},{4},{6},{2,4},{4,6},{2,4,6}}

其中异或是按位异或,即C/C++中的"^"运算符"

 

"这么简单,看我三下五除二解决了这题,三分钟后你就叫小蛤没得商量了!你答应给我,告诉我小C的消息可不许反悔!"

"哼,爷蛤蟆大仙是那种会反悔的人吗,而且你不可能会做这题的,看你一会怎么给自己找台阶下!"

注意异或有两个常用的性质(下面的"^"代表异或运算)

  1.   a^a=0

  2.   a^0=a

 

Input

单组数据

开头是一个整数n代表n个数字,n<=5*105

接下来有n个数a1,a2,a3,……an  ,(0<=ai<230)

 

Output

输出所有子区间异或和的异或和

SampleInput
4
3 3 6 7
SampleOutput
0
hint:
所有子区间与对应的异或和如下:
{3}                    3
{3,3}                  0
{3,3,6}                6
{3,3,6,7}              1
{3}                    3
{3,6}                  5
{3,6,7}                2
{6}                    6
{6,7}                  1
{7}                    7

所以答案=3^0^6^1^3^5^2^6^1^7=0

 【思路】:

你可以发现一个规律,第一个位置的数出现的次数为n,第二个位置的数出现的次数为2*(n-1)....到中间位置

比如

1 2 3

3 4 3

1 2 3 4

4 6 6 4

1 2 3 4 5

5 8 9 8 5

红色为单个位置上的出现个数

然后两边对称,我的思路是先把每个位置的次数打个表。再根据题意给的

  1.   a^a=0

  2.   a^0=a

因为如果在这个位置的次数为奇数 的话,肯定等于它本身。

为偶数,肯定等于0

进行有运算后保存,最后再进行一次O(n)的求和。

就可以得到答案了。

贴上代码(运行时间:40ms)

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
ll math[500005];
ll data[500005];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {memset(math,0,sizeof(math));
        ll a;
        ll c=n;
        ll b=1;
        int flag=0;
        if(n%2==0)
        {
        a=n/2;
        }
        else
            {a=n/2+1;
            flag=1;
            }
        for(int i=0;i<a;i++)
        {
            math[i]=c*(b);
            b++;
            c--;
        }
        int j;
        if(flag==0)
            j=a-1;
        else
            j=a-2;
        for(int i=a;i<n;i++)
        {
            math[i]=math[j];
            j--;
        }
        for(int i=0;i<n;i++)
            {scanf("%lld",&data[i]);
            if(math[i]%2==0)
                data[i]=0;
            }
            ll sum=0;
        for(int i=0;i<n;i++)
        {
            sum^=data[i];
        }
        printf("%lld\n",sum);
    }
    return 0;
}

 

 

posted @ 2018-05-14 11:05  moxin0509  阅读(222)  评论(0编辑  收藏  举报