CS Academy Round #32 Light Count

内存限制了12MB.

所以输入是题目给的随机数。

数据大小是5*10^7,可以将其分成781250份,每份一个ULL表示状压,最后树状数组做。

学到了__builtin_popcountll(),快速得到一个二进制数中有几个1.


代码:

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
const double PI = acos(-1.0);
const double eps = 1e-10;
int dcmp(double x) { if(fabs(x) < eps) return 0; else return x<0?-1:1; }
const int INF = 0x3f3f3f3f;
const int N = 781250+5;

int b[N], sz;
ull a[N];

struct RandGen {
    int x, y, z;

    int nextInt() {
        int t = x ^ (x << 11);
        x = y;
        y = z;
        z ^= (z >> 19) ^ t ^ (t >> 8);
        return z;
    }

    int random(int x) { return nextInt() % x; }
};

void init(int n) {
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    sz = (n+63)/64;
}

int lowbit(int x) { return x&-x; }

void add(int x, int d) {
    while(x <= sz) {
        b[x] += d;
        x += lowbit(x);
    }
}

void flipPosition(int poz) {
    int x = (poz>>6)+1;
    ull mask = 1llu<<(poz&63);
    if(mask & a[x]) {
        a[x] ^= mask;
        add(x, -1);
    }
    else {
        a[x] ^= mask;
        add(x, 1);
    }
}

int sum(int poz) {
    if(poz < 0) return 0;
    int ret = 0, x = (poz>>6)+1;
    ull mask = 1llu<<(poz&63);
    if(mask > 0) mask += mask-1;
    ret += __builtin_popcountll(a[x]&mask);
    x--;
    while(x > 0) {
        ret += b[x];
        x -= lowbit(x);
    }
    return ret;
}

int getCount(int st, int fn) { return sum(fn)-sum(st-1); }

int main() {
    int n, m;
    RandGen rng;
    cin >> n >> m >> rng.x >> rng.y >> rng.z;
    init(n);

    long long hashSol = 0;
    for (long long i = 0; i < m; i++) {
        if (rng.random(2) == 0) {
            const int poz = rng.random(n);
            flipPosition(poz);
        }
        else {
            int st = rng.random(n), fn = rng.random(n);
            if (st > fn) swap(st, fn);
            hashSol ^= i * getCount(st, fn);
        }
    }

    cout << hashSol << "\n";
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值