硝基甲苯之魇

题目链接:https://ac.nowcoder.com/acm/contest/95323/K

题意:

给定一个长度为n的数组,求所有[l,r]区间xor等于区间gcd的个数(l<r)

思路:

不妨固定左端点l,a[l]=x,发现右端点在扩增的时候,区间gcd最多变化logx次,因此可以二分出区间gcd的变化点p

同时用ST表求出区间[p1,p2]gcd大小,设为g,那么区间pre[r] xor pre[l-1] = g => pre[r]= g xor pre[l-1]

(其中r属于[p1,p2]且r不能为l),通过map套vector上二分能求出这段区间中pre[r]的数的个数

int Log[maxn];
void init(){
    Log[1]=0;
    for(int i=2;i<=2e5;i++){
        Log[i] =Log[i/2]+1;
    }
}

void solve(){
    int n;cin>>n;
    vector<int>a(n+1);
    rep(i,1,n)cin>>a[i];
    vector<vector<int>>f(n+1,vector<int>(27));
    rep(i,1,n)f[i][0]=a[i];
    rep(j,1,26){
        for(int i=1;i+(1ll<<j)-1<=n;i++){
            f[i][j]=__gcd(f[i][j-1],f[i+(1ll<<j-1)][j-1]);
        }
    }
    auto query =[&](int l,int r)->int{
        int k=Log[r-l+1];
        return __gcd(f[l][k],f[r-(1ll<<k)+1][k]);
    };

    vector<int>pre(n+1);
    rep(i,1,n){
        pre[i]=(pre[i-1]^a[i]);
    }
    map<int,vector<int>>cnt;
    rep(i,1,n)cnt[pre[i]].pb(i);
    int ans=0;
    auto cal=[&](int x,int lt,int rt)->int{
        auto itl=lower_bound(cnt[x].begin(),cnt[x].end(),lt);
        int left=0;
        if(itl==cnt[x].end())return 0;
        else left=lower_bound(cnt[x].begin(),cnt[x].end(),lt)-cnt[x].begin();
        auto itr=upper_bound(cnt[x].begin(),cnt[x].end(),rt);
        if(itr==cnt[x].end()){
            int m=cnt[x].size();
            return (m-left);
        }else{
            int right=upper_bound(cnt[x].begin(),cnt[x].end(),rt)-cnt[x].begin();
            return (right-left);
        }
    };
   
    for(int l=1;l<=n;l++){
        int L=l,R=n;
        int u=a[l];
        while(L<=n){
            int tmp=L;
            int ed=-1;
            while(L<=R){
                int mid = L+R>>1;
                if(query(l,mid)==u){
                    L=mid+1;
                    ed=mid;
                }else R=mid-1;
            }
            if(ed==-1)break;

            int x= (pre[l-1]^u);
            ans += cal(x,max(l+1,tmp),ed);

            if(ed+1>n)break;
            u=query(l,ed+1);
            L=ed+1;
            R=n;
        }
    }
    cout<<ans<<endl;
}
posted @ 2025-09-22 16:38  Marinaco  阅读(10)  评论(0)    收藏  举报
//雪花飘落效果