Comet OJ - Contest #9 & X Round 3

                                           【XR-3】Unknown Mother-Goose(暴力,位运算,分块)

解:

    暴力:开一个有1e9bit的ull数组,对于集合中每一个数x,令第x,2x,3x...位为1,只要找连续3位为1就好,所以答案就为连续3个1的个数,可以用__builtin_popcountll(t&(t>>1)&(t>>2))来求;

    分块:为减小复杂度,可以把64位分为一块(也就是1个ull),当遇到集合中一个数x时:

                           x>=64时:枚举所有x的倍数;

                            x<64时:先算出前x个块,后面的块由前x个块循环组成。

    求解:答案由块内和块间组成,把两部分加起来就可以了。

    时间复杂度:O(|S|*n/64)

    理论上复杂度高,但是寻址连续并且不会频繁调用系统栈,可以过。

    注意:3<=x<=n;所以a[0]第一位不能区,a[m]超过n的位不能取。

代码:

#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int N=1e9+9;
int n,cnt;
ull a[(N>>6)+10],b[78];
int main(){
    cin>>n>>cnt;
    int m=(n>>6);
    while(cnt--){
        int x;
        cin>>x;
        if(x>64){
            for(int i=x;i<=n;i+=x)a[i>>6]|=(1ll<<(i&63));
        }else{
            for(int i=0;i<x;i++)b[i]=0;
            for(int i=0;i<64*x;i+=x)b[i>>6]|=(1ll<<(i&63));
            for(int i=0,j=0;i<=m;i++,j=(j==x-1)?0:j+1)a[i]|=b[j];
        }
    }
    a[m]&=((1ll<<((n+1)&63))-1);//x<=n
    if(a[0]&1)a[0]^=1;//题目要求x>=3
    int ans=0;
    for(int i=0;i<=m;i++)ans+=__builtin_popcountll(a[i]&(a[i]>>1)&(a[i]>>2));
    for(int i=1;i<=m;i++){
        ull t=(a[i-1]>>62)|((a[i]&3)<<2);
        ans+=__builtin_popcountll(t&(t>>1)&(t>>2));
    }
    cout<<ans<<endl;
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值