期望得分:100+100+40=240
实际得分:100+0+40=140
二进制拆分、二进制前缀和
#include<cstdio> #include<iostream> using namespace std; typedef long long LL; #define N 100001 int a[N],b[N],c[N]; const int mod=1e9+7; int suma[N][32],sumb[N][32]; int bit[31]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } int finda(int r,int wh) { long long tot=0; for(int i=0;i<=30;i++) if(wh&bit[i]) tot=(tot+1ll*(r-suma[r][i])*bit[i])%mod; else tot=(tot+1ll*suma[r][i]*bit[i])%mod; return int(tot%mod); } int findb(int r,int wh) { long long tot=0; for(int i=0;i<=30;i++) if(wh&bit[i]) tot=(tot+1ll*(r-sumb[r][i])*bit[i])%mod; else tot=(tot+1ll*sumb[r][i]*bit[i])%mod; return int(tot%mod); } int main() { freopen("xorarray.in","r",stdin); freopen("xorarray.out","w",stdout); int n; scanf("%d",&n); int len,x; for(int i=1;i<=n;i++) { read(a[i]); len=0; x=a[i]; while(x) suma[i][len++]=suma[i-1][len]+(x&1),x/=2; for(int j=len;j<=30;j++) suma[i][j]=suma[i-1][j]; } for(int i=1;i<=n;i++) { read(b[i]); len=0; x=b[i]; while(x) sumb[i][len++]=sumb[i-1][len]+(x&1),x/=2; for(int j=len;j<=30;j++) sumb[i][j]=sumb[i-1][j]; } bit[0]=1; for(int i=1;i<=30;i++) bit[i]=bit[i-1]<<1; c[1]=a[1]^b[1]; for(int k=2;k<=n;k++) { c[k]=c[k-1]; c[k]=(c[k]+finda(k-1,b[k]))%mod; c[k]=(c[k]+findb(k,a[k]))%mod; } for(int i=1;i<=n;i++) printf("%d ",c[i]); }