1. 程式人生 > >2018 FJUT acm校賽 b題 第二集:以後我就叫你小蛤了

2018 FJUT acm校賽 b題 第二集:以後我就叫你小蛤了

else 規律 pan RM 運行時間 std 等於 AI ane

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

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;
}

2018 FJUT acm校賽 b題 第二集:以後我就叫你小蛤了