洛谷3760,异或和

一开始看到这题,n只到 105 ,在想能不能暴力卡常一波艹过去,最后本地死活要跑1.6s,要是机子快点-1s?就好了。
然后我太菜了,死活做不出,百度出了个题解,挺好的。

#include<cstdio>
#include<cctype>
inline int getint(){
    int x=0;
    char c=getchar();
    while(!isdigit(c))c=getchar();
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return x;
}
struct treearray{
    static const int maxn=5100000;
    int a[maxn],l[maxn],n;
    void init(int x){
        n=x;
        for(int i=1;i<=x;i++)a[i]=0;
    }
    void add(int x,int y){
        ++x;
        for(int i=x;i<=n;i+=i&-i)a[i]+=y;
    }
    int query(int x){
        ++x;
        int ans=0;
        for(int i=x;i;i-=i&-i)ans+=a[i];
        return ans;
    }
    int sum(int x,int y){
        return query(y)-query(x-1);
    }
}t1,t0;
const int N=100010;
int n,i,j,m,s[N],x,y,ans;
int main(){
    n=getint();
    for(i=1;i<=n;++i)s[i]=getint()+s[i-1];
    for(j=0;1<<j<=s[n];++j){
        t1.init(x=1<<j);
        t0.init(x);
        y=0;
        //t0.add(0,1);
        for(i=1;i<=n;++i)
            if(x&s[i])y+=1+t0.query(s[i]&(x-1))+t1.sum((s[i]&(x-1))+1,x-1),t1.add(s[i]&(x-1),1);
                else y+=t1.query((s[i]&(x-1)))+t0.sum((s[i]&(x-1))+1,x-1),t0.add(s[i]&(x-1),1);
        ans|=(y&1)<<j;
    }
    printf("%d\n",ans);
    return 0;
}

下面是暴力卡常的代码,强行CPU并发,并没有出现所谓的 O(n2) 106 ,可能是我姿势不对吧,哪位大佬能教教我正确的循环展开姿势?

#pra\
gma GCC optimize("O2")
#include<iostream>
#include<cstdio>
#include<cctype>
using namespace std;
inline int getint(){
    int x=0;
    char c=getchar();
    while(!isdigit(c))c=getchar();
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return x;
}
const int N=100010;
int s[N],x,n,i,ans,*p,*e;
int main(){
    n=getint();
    for(i=1;i<=n;++i){
        x=getint();
        s[i]=s[i-1]+x;
    }
    e=s+n;
    for(i=1;i<=n;++i){
        x=s[i-1];
        for(p=&s[i];p+14<=e;p+=15){
            ans^=((*p)-x)^(*(p+1)-x)^(*(p+2)-x)^(*(p+3)-x)^(*(p+4)-x)^(*(p+5)-x)^(*(p+6)-x)^(*(p+7)-x)^(*(p+8)-x)
                ^(*(p+9)-x)^(*(p+10)-x)^(*(p+11)-x)^(*(p+12)-x)^(*(p+13)-x)^(*(p+14)-x);
        }
        for(;p<=e;++p)ans^=(*p)-x;
    }
    cout<<ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值