4888 [Tjoi2017]異或和
阿新 • • 發佈:2018-08-19
max int pri 區間 its oss -- amp i++
題面
戳這裏
簡要題解
做法一
因為所有數的和才100w,所以我們可以直接求出所有區間和。
直接把前綴和存到一個權值數組,再倒著存一遍,大力卷積一波。
這樣做在bzoj目前還過不了,但是luogu開O2,最慢的點才500ms左右。
#include<bits/stdc++.h> #define For(i,x,y) for (register int i=(x);i<=(y);i++) #define Dow(i,x,y) for (register int i=(x);i>=(y);i--) #define cross(i,u) for (register int i=first[u];i;i=last[i]) using namespace std; typedef long long ll; inline ll read(){ ll x=0;int ch=getchar(),f=1; while (!isdigit(ch)&&(ch!=‘-‘)&&(ch!=EOF)) ch=getchar(); if (ch==‘-‘){f=-1;ch=getchar();} while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} return x*f; } const int N = 4e6+10; int m,ans,pre[N]; struct node{ double x,y; inline node operator + (const node &b)const{return (node){x+b.x,y+b.y};} inline node operator - (const node &b)const{return (node){x-b.x,y-b.y};} inline node operator * (const node &b)const{return (node){x*b.x-y*b.y,x*b.y+y*b.x};} }a[N],b[N]; int n,l,pos[N]; inline void init(){ for (n=1;n<=(pre[m]<<1);n<<=1,l++); For(i,0,n-1) pos[i]=(pos[i>>1]>>1)|((i&1)<<(l-1)); } const double pi = 3.1415926535897932; inline void FFT(node *a,int f){ For(i,0,n-1) if (i<pos[i]) swap(a[i],a[pos[i]]); node x,y; for (register int i=1;i<n;i<<=1){ node wn=(node){cos(pi/i),f*sin(pi/i)}; for (register int j=0;j<n;j+=i<<1){ node w=(node){1,0}; for (register int k=0;k<i;k++,w=w*wn) x=a[j+k],y=w*a[j+k+i],a[j+k]=x+y,a[j+k+i]=x-y; } } if (f<0) For(i,0,n-1) a[i].x=a[i].x/n+0.5; } int main(){ m=read(),a[0].x=1; For(i,1,m) pre[i]=pre[i-1]+read(),++a[pre[i]].x; For(i,0,pre[m]) b[pre[m]-i].x=a[i].x; init();FFT(a,1),FFT(b,1); For(i,0,n-1) a[i]=a[i]*b[i]; FFT(a,-1); //For(i,0,n-1) printf("%d ",(int)a[i].x);puts(""); For(i,0,pre[m]) if ((int)a[i].x&1) ans^=(-(i-pre[m])); printf("%d",ans); }
做法二
考慮拆位,大力分類討論,再加一個樹狀數組維護下。
#include<bits/stdc++.h> #define For(i,x,y) for (register int i=(x);i<=(y);i++) #define Dow(i,x,y) for (register int i=(x);i>=(y);i--) #define cross(i,u) for (register int i=first[u];i;i=last[i]) using namespace std; typedef long long ll; inline ll read(){ ll x=0;int ch=getchar(),f=1; while (!isdigit(ch)&&(ch!=‘-‘)&&(ch!=EOF)) ch=getchar(); if (ch==‘-‘){f=-1;ch=getchar();} while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} return x*f; } const int N = 1e6+10; int n,cnt,Max,ans,pre[N]; struct BIT{ int c[N]; inline void Add(int x,int y){for (;x<=pre[n];x+=x&-x) c[x]+=y;} inline int Query(int x){int ans=0;for (;x;x-=x&-x) ans+=c[x];return ans;} }t[2]; int main(){ n=read(); For(i,1,n) pre[i]=pre[i-1]+read(); for (int i=1;i<=pre[n];i<<=1){ cnt=Max=0; For(j,0,n){ int x=((pre[j]&i)>0),y=pre[j]&(i-1); Max=max(Max,y),cnt+=t[x^1].Query(y+1)+t[x].Query(Max+1)-t[x].Query(y+1),t[x].Add(y+1,1); } For(j,0,pre[n]) t[0].c[j]=t[1].c[j]=0; ans|=(cnt&1)*i; } printf("%d",ans); }
4888 [Tjoi2017]異或和