1 条题解
-
0
自动搬运
来自洛谷,原作者为

NaCly_Fish
北海虽赊,扶摇可接。搬运于
2025-08-24 22:11:48,当前版本为作者最后更新于2019-09-24 22:25:09,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
出题人怎么一直不发题解啊,,
那我就来水一篇好了(首先,这题看起来时什么 之类的做法,然而实际上就是 的 bitset 大暴力。
做法也就是开一个 的数组,对于 中的每个数 ,把 的倍数都设为 ,统计数组中有多少组 个连续的 即是答案。
然后把这个过程用 bitset 优化一下就可以了(
另外要注意的一点, 是正整数,或许要把第 项的贡献判掉ps:这个东西和分块的思想很像,不过是基于CPU的运算优化的。
代码:
#include<cstdio> #include<iostream> #include<cstring> #define N 1000000003 #define reg register using namespace std; unsigned long long bs[(N>>6)+10]; unsigned long long tmp[65]; int n,m,s,l,ans; inline int count(unsigned long long x){ reg int res = 0; while(x){ res += x&1; x >>= 1; } return res; } int main(){ scanf("%d%d",&n,&s); m = (n>>6)+1; while(s--){ scanf("%d",&l); if(l<64){ //两种情况判一下,保证加入的复杂度是 n/w memset(tmp,0,sizeof(tmp)); for(reg int i=0;i<(l<<6);i+=l) tmp[i>>6] |= 1ull<<(i&63); //加入的数比较小,开另一个数组,作为重复单元 for(reg int i=0;i<=m;i+=l) for(reg int j=0;j<l;++j) bs[i+j] |= tmp[j]; }else{ for(reg int i=0;i<=n;i+=l) bs[i>>6] |= 1ull<<(i&63); } } --m; if((n&63)!=63) bs[m] &= (1ull<<(n+1-(m<<6)))-1; //特判一下最后一块 bs[0] &= -2ull; //除去第 0 项 for(reg int i=0;i<=m;++i) ans += count(bs[i]&(bs[i]<<1)&(bs[i]<<2)); for(reg int i=1;i<=m;++i) ans += count(bs[i]&(bs[i-1]>>62)&((bs[i-1]>>63)|(bs[i]<<1))); printf("%d",ans); return 0; }
- 1
信息
- ID
- 4538
- 时间
- 2000ms
- 内存
- 250MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者