zoukankan      html  css  js  c++  java
  • 【TJOI2017】异或和

    题目描述

    在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题目都是与序列的连续和相关的。所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的简单。但今天小明遇到了一个序列和的难题,这个题目不仅要求你快速的求出所有的连续和,还要快速的求出这些连续和的异或值。小明很快的就求出了所有的连续和,但是小明想考考你,在不告诉连续和的情况下,让你快速的求出序列所有的连续和的异或值。

    输入格式

    第一行输入一个(n),表示这序列的数字个数。

    第二行输入(n)个数字(a_1,a_2,a_3)...(a_n),代表这个序列。

    (0≤a_1,a_2,)...(,a_n,0≤a_1+a_2+)...(+a_n≤10^6)

    输出格式,

    输出这个序列所有的连续和的异或值。

    数据范围

    对于(20\%)的数据,(1≤n≤1000)
    对于(100\%)的数据,(1≤n≤10^5)


    直接暴力(O(n^2)),可以获得(20)

    考虑按位枚举,题目保证了(0≤a_1+a_2+)...(+a_n≤10^6)

    那么显然,我们最多只需要枚举(20)

    对于枚举的每一位,我们希望快速地算出有多少和在这一位上有贡献(1)

    显然,一个和我们可以通过前缀和的预处理,(sum_{i=l}^r=sum[r]-sum[l-1])

    当我们知道了当前(x)(sum[x])的第(i)位为(1)的时候,我们要知道以这一位为结束区间有多少贡献为(1)

    显然只有两种情况,当(sum[y](y<x))的第(i)位也是(1)的时候,(y)的后面几位必须比(x)大才可以使得(x)的前面退位,使得区间(sum_{i=y-1}^x)产生贡献

    (sum[y](y<x))的第(i)位也是(0)的时候,(y)的后面几位必须比(x)小才可以保住(x)的贡献

    而满足这样的两个条件,我们可以用树状数组来简单地维护一下

    (x)的第(i)位为(0)的时候,一样的分析一下就好了

    还有一个细节就是,计算贡献的时候,可能答案会超过int,那就让他自然溢出好了,就是最后计算的时候注意取模的正负即可


    #include<cstdio>  
    #include<iostream>  
    #include<algorithm>  
    #include<cstdlib>  
    #include<cstring>
    #include<string>
    #include<climits>
    #include<vector>
    #include<cmath>
    #include<map>
    #define LL long long
     
    using namespace std;
     
    inline char nc(){
      static char buf[100000],*p1=buf,*p2=buf;
      if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
      return *p1++;
    }
     
    inline void read(int &x){
      char c=nc();int b=1;
      for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
      for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
    }
     
    inline void read(LL &x){
      char c=nc();LL b=1;
      for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
      for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
    }
    
    inline int read(char *s)
    {
    	char c=nc();int len=0;
    	for(;!((c>='A' && c<='Z')||(c>='a' && c<='z'));c=nc()) if (c==EOF) return 0;
    	for(;((c>='A' && c<='Z')||(c>='a' && c<='z'));s[len++]=c,c=nc());
    	s[len++]='';
    	return len;
    }
    
    inline void read(char &x){
      for (x=nc();!(x=='?' || x=='+' || x=='-');x=nc());
    }
    
    int wt,ss[19];
    inline void print(int x){
    	if (x<0) x=-x,putchar('-'); 
    	if (!x) putchar(48); else {
    	for (wt=0;x;ss[++wt]=x%10,x/=10);
    	for (;wt;putchar(ss[wt]+48),wt--);}
    }
    inline void print(LL x){
    	if (x<0) x=-x,putchar('-');
    	if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
    }
    
    int n,a[100010],p2[100],c0[2000010],c1[2000010],ans[100];
    const int M=20;
    
    void change0(int x,int y)
    {
    	x++;
    	while (x<=p2[M]) c0[x]+=y,x+=x&(-x);
    }
    void change1(int x,int y)
    {
    	x++;
    	while (x<=p2[M]) c1[x]+=y,x+=x&(-x);
    }
    int query0(int x)
    {
    	x++;
    	int res=0;
    	while (x>0) res+=c0[x],x-=x&(-x);
    	return res;
    }
    int query1(int x)
    {
    	x++;
    	int res=0;
    	while (x>0) res+=c1[x],x-=x&(-x);
    	return res;
    }
    
    int main()
    {
    	read(n);
    	for (int i=1;i<=n;i++)
    		read(a[i]);
    	p2[0]=1;
    	for (int i=1;i<=M;i++) p2[i]=2*p2[i-1];
    	memset(ans,0,sizeof(ans));
    	for (int i=1;i<=M;i++)
    	{
    		int s=0;
    		for (int j=1;j<=n;j++)
    		{
    			s+=a[j];
    			if ((s&p2[i-1])!=0) ans[i]++;
    			if ((s&p2[i-1])==0)
    			{
    				ans[i]+=query0(p2[i-1]-1)-query0(s%p2[i-1]);
    				ans[i]+=query1(s%p2[i-1]);
    			}
    			else
    			{
    				ans[i]+=query0(s%p2[i-1]);
    				ans[i]+=query1(p2[i-1]-1)-query1(s%p2[i-1]);
    			}
    			if ((s&p2[i-1])==0) change0(s%p2[i-1],1);else change1(s%p2[i-1],1);
    		}
    		s=0;
    		for (int j=1;j<=n;j++)
    		{
    			s+=a[j];
    			if ((s&p2[i-1])==0) change0(s%p2[i-1],-1);else change1(s%p2[i-1],-1);
    		}
    	}
    	int res=0,s=1;
    	for (int i=1;i<=M;i++)
    		res+=s*abs(ans[i]%2),s*=2;
    	print(res),puts("");
    	return 0;
    }
    
  • 相关阅读:
    助教学期总结
    助教学习总结
    第十二周助教总结
    第十一周助教总结
    第十周助教总结
    第九周助教总结
    第八周助教总结
    第八周作业——基础
    19秋第三周助教总结
    助教学习总结
  • 原文地址:https://www.cnblogs.com/xiejiadong/p/6815269.html
Copyright © 2011-2022 走看看