jzoj5835 Prime 区间筛

Description


这里写图片描述

Solution


这是今天最签到的一题,死于捆绑测试

考虑区间筛。我们预处理 min(k,r) m i n ( k , r ) 的质数,然后用这些质数筛出区间[l,r]内的类质数
然后就做完了

这个杯具告诉我们可以暴力和正解一起交,这样正解挂了还可以有暴力分qaq

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#define rep(i,st,ed) for (register LL i=st,_=ed;i<=ed;++i)

typedef long long LL;
const int MOD=44775803;
const int N=10000005;

LL prime[N],hash[MOD+5];

bool not_prime[N],rec[MOD+5];

__attribute__((optimize("O2")))
inline int get_hash(LL x) {
    int i=x%MOD;
    for (;hash[i]&&hash[i]!=x;i=i%MOD+1);
    return i;
}

__attribute__((optimize("O2")))
inline void pre_work(LL n,LL l,LL r,LL k) {
    rep(i,2,n) {
        if (!not_prime[i]) {
            prime[++prime[0]]=i;
        }
        for (int j=1;j<=prime[0]&&prime[j]<=k&&i*prime[j]<=n;j++) {
            not_prime[i*prime[j]]=1;
            if (i%prime[j]==0) break;
        }
    }
    l=std:: max(l,n-1);
    rep(i,1,prime[0]) if (prime[i]<=k) {
        LL st=(l-1)/prime[i]+1;
        LL ed=r/prime[i];
        rep(j,st,ed) {
            LL tmp=prime[i]*j;
            int pos=get_hash(tmp);
            if (hash[pos]==0) {
                hash[pos]=tmp;
                rec[pos]=1;
            }
            // printf("%lld\n", prime[i]*j);
        }
    }
}

bool is_prime(LL x,LL k) {
    for (int i=1;prime[i]<=k&&prime[i]*prime[i]<=x&&i<=prime[0];i++) {
        if (x%prime[i]==0) return false;
    }
    return true;
}

__attribute__((optimize("O2")))
int main(void) {
    freopen("prime.in","r",stdin);
    freopen("prime.out","w",stdout);
    LL l,r,k,ans=0; scanf("%lld%lld%lld",&l,&r,&k);
    if (r<=10000000) {
        pre_work(r,l,r,k);
        rep(i,l,r) if (!not_prime[i]) {
            ans^=i;
        }
        printf("%lld\n", ans);
        return 0;
    }
    pre_work(1+sqrt(r),l,r,k);
    rep(i,l,r) {
        int pos=get_hash(i);
        if (!hash[pos]||!rec[pos]||hash[pos]!=i) {
            ans^=i;
        }
    }
    printf("%lld\n", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值