https://www.luogu.com.cn/problem/P5539
想到了,但没有完全想到
先丢一个时间复杂度是
O
(
n
∣
S
∣
w
)
O(\frac{n|S|}{w})
O(wn∣S∣)
要手写
b
i
t
s
e
t
bitset
bitset
把
∣
S
∣
|S|
∣S∣中的每个数的倍数都设为
1
1
1
统计连续三个
1
1
1的个数
具体实现看代码吧
code:
#include<bits/stdc++.h>
#define ull unsigned long long
#define lowbit(x) (x & -x)
using namespace std;
int count(ull x) {
int ret = 0;
while(x) ret ++, x -= lowbit(x);
return ret;
}
const int N = 1000000000 / 63;
ull a[N << 1], b[71];
int n, m, gs;
void insert(int x) {
if(x >= 64) for(int i = 0; i <= n; i += x) a[i >> 6] |= (1ull << (i & 63));
else {
for(int i = 0; i < 64; i ++) b[i] = 0;
for(int i = 0; i < 64; i ++) b[(i * x) >> 6] |= (1ull << ((i * x) & 63));
//for(int i = 0; i < 64; i ++) printf("%llu ", b[i]); printf("\n");
for(int i = 0; i <= gs; i += x) {
for(int j = 0; j < x; j ++) {
a[i + j] |= b[j];
}
}
}
}
void print(ull x) {
for(int i = 0; i < 64; i ++) printf("%llu", (x >> i) & 1); printf("\n");
}
int main() {
scanf("%d%d", &n, &m);
gs = n >> 6;
while(m --) {
int x;
scanf("%d", &x); insert(x);
//break;
}
for(int i = (gs << 6), t = 0; i < ((gs + 1) << 6); i ++, t ++) if(((a[gs] >> t) & 1) && i > n) {
// printf("*%d %d ", i, t);
a[gs] ^= (1ull << t);
}
if(a[0] & 1) a[0] ^= 1;
int ans = 0;
//for(int i = 0; i <= gs; i ++) print(a[i]);
for(int i = 0; i <= gs; i ++)
ans += count(a[i] & ((a[i] << 1) | (a[i - 1] >> 63)) & ((a[i] << 2) | (a[i - 1] >> 62)));
printf("%d", ans);
return 0;
}