首页 > 其他 > 详细

[Luogu 3794]签到题IV

时间:2019-09-27 21:54:31      阅读:90      评论:0      收藏:0      [点我收藏+]

Description

题库链接

给定长度为 \(n\) 的序列 \(A\)。求有多少子段 \([l,r]\) 满足

\[ \left(\gcd_{l\leq i\leq r}A_i\right) \oplus\left(\bigcup_{l\leq i\leq r}A_i\right)=k \]

其中 \(\oplus\) 表示按位异或,\(\cup\) 表示按位或。

\(1\leq n,A_i\leq 500000\)

Solution

这道题和[JSOI 2015]最大公约数一样啊。

可知,一个确定的右端点,其左端点随便取,\(\gcd\) 和按位或是不超过 \(\log\) 种的。

直接存下不同的值及其对应的最左端点。总复杂度为 \(O(n\log^2 A_i)\)

Code

#include <bits/stdc++.h>
#define ll long long
#define pii pair<int, int>
#define fr first
#define sc second
#define pb push_back
using namespace std;
const int N = 500000+5;

int n, K, a[N];
vector<pii > g[N], o[N];
pii tg, to;
ll ans;

int gcd(int a, int b) {return b ? gcd(b, a%b) : a; }
int main() {
    scanf("%d%d", &n, &K);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for (int i = 1; i <= n; i++) {
        int szg = g[i-1].size(), szo = o[i-1].size(), j = 0, k = 0, cg = 0, co = 0;
        g[i-1].pb(pii(0, i)), o[i-1].pb(pii(0, i));
        while (j < szg && k < szo) {
            tg = g[i-1][j], to = o[i-1][k];
            tg.fr = gcd(a[i], tg.fr);
            to.fr = (a[i]|to.fr);
            if ((tg.fr^to.fr) == K) ans += min(g[i-1][j+1].sc, o[i-1][k+1].sc)-max(tg.sc, to.sc);
            if (cg == 0 || tg.fr != g[i][cg-1].fr) g[i].pb(tg), ++cg;
            if (co == 0 || to.fr != o[i][co-1].fr) o[i].pb(to), ++co;
            if (g[i-1][j+1].sc == o[i-1][k+1].sc) ++j, ++k;
            else if (g[i-1][j+1].sc < o[i-1][k+1].sc) ++j;
            else ++k;
        }
        tg = pii(a[i], i), to = pii(a[i], i);
        if ((tg.fr^to.fr) == K) ans++;
        if (cg == 0 || tg.fr != g[i][cg-1].fr) g[i].pb(tg), ++cg;
        if (co == 0 || to.fr != o[i][co-1].fr) o[i].pb(to), ++co;
    }
    printf("%lld\n", ans);
    return 0;
}

[Luogu 3794]签到题IV

原文:https://www.cnblogs.com/NaVi-Awson/p/11600488.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!