51NOD 区间的价值 V2

http://www.51nod.com/contest/problem.html#!problemId=1674

因为题目要求的只是& 和 |

这两个运算。而这两个运算产生的值是有限的。

&,当产生的值是0的时候,就不会再变化了。

|,当产生的值是(111111111)的时候,值也不变化了。

所以每种运算的状态数也就30种不同的情况。

所以考虑分治,

先算出[mid + 1, R]中的值,就是固定mid + 1,一直向右边&和|

然后在[mid, L]从mid开始一直向左边&和|,这样的话,如果已经得到了右半区间的各种情况,就可以快速算出整个区间的情况。

把and起来得值和or起来得值进行统计,因为每种运算只有30种情况,所以当他们都一样的时候,就压缩在一起,统计有多少个不同的值即可。

30 + 30 = 60

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 100000 + 20;
LL a[maxn];
LL ans;
const int MOD = 1000000007;
const LL one = 1;
int AND[900 + 2], OR[900 + 2]; //全部是0或者全部是1后,状态不会变了
int sum[900 + 2]; //所以两种状态相同的时候,也就900种状态
void calc(int L, int R) {
    if (L == R) {
        ans = (ans + a[L] * a[L] % MOD) % MOD;
        return;
    }
    int mid = (L + R) >> 1;
    int len = 1;
    AND[len] = OR[len] = a[mid + 1];
    sum[len] = 1;
    for (int i = mid + 2; i <= R; ++i) {
        if ((AND[len] & a[i]) == AND[len] && (OR[len] | a[i]) == OR[len]) {
            sum[len]++;
        } else {
            ++len;
            AND[len] = AND[len - 1] & a[i];
            OR[len] = OR[len - 1] | a[i];
            sum[len] = 1;
        }
    }
    LL nowAnd = (one << 31) - 1;
    LL nowOr = 0;
    for (int i = mid; i >= L; --i) {
        nowAnd = nowAnd & a[i];
        nowOr |= a[i];
        for (int j = 1; j <= len; ++j) {

            ans += (nowAnd & AND[j]) * (nowOr | OR[j]) % MOD * sum[j] % MOD;
            ans %= MOD;
        }
    }
    calc(L, mid);
    calc(mid + 1, R);
}
void work() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    calc(1, n);
    cout << ans << endl;
}
int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    IOS;
    work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6017544.html