jzoj5835 Prime 区间筛

Description


这里写图片描述

Solution


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

考虑区间筛。我们预处理min(k,r)min(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;
}
### 区间筛算法概述 区间筛(Segmented Sieve)是一种用于在给定范围内查找素数的有效算法。相比于传统的埃拉托斯特尼筛法,区间筛更适合处理较大的数值范围,尤其是当内存有限的情况下。 #### 实现方式 为了实现区间筛算法,通常会分为两个阶段: 1. **预筛选小范围内的素数** 首先,在较小的范围内(通常是根号级别大小),使用标准的埃拉托斯特尼筛法找出所有的素数。这部分操作可以在常量时间内完成,并且占用较少的空间资源[^3]。 2. **分段处理大范围的数据** 接下来,将整个待查区间分割成若干个小片段来逐一检验其中可能存在的质数。对于每一个子区间,仅需考虑那些小于等于该区间的平方根的小素因子即可有效地排除掉合数候选者们。 ```python import math def segmented_sieve(low, high): limit = int(math.sqrt(high)) + 1 prime = [True] * limit p = 2 while (p * p <= limit): if prime[p]: for i in range(p * p, limit, p): prime[i] = False p += 1 primes = [] for p in range(2, limit): if prime[p]: primes.append(p) n = high - low + 1 mark = [False] * (n + 1) for i in range(len(primes)): loLim = int(math.floor(low / primes[i]) * primes[i]) if loLim < low: loLim += primes[i] for j in range(loLim, high + 1, primes[i]): mark[j-low] = True for i in range(n): if not mark[i] and (i + low) != 1: print(i + low) segmented_sieve(10, 20) ``` 此代码实现了上述提到的方法,通过预先计算一个小范围内的所有素数并利用这些信息去标记更大的区间中的非素数位置,最终输出指定闭区间 `[low,high]` 内的所有素数。 #### 应用场景 - **密码学领域**:由于许多加密技术依赖于大整数分解难题,因此快速生成大量随机分布的大素数成为构建安全密钥的基础之一。 - **分布式系统测试工具**:模拟网络延迟或者丢包情况时需要用到伪随机序列发生器;而基于线性同余式的PRNG容易被预测出来,故采用更复杂的机制如Mersenne Twister配合上高质量种子源——即由区间筛产生的大批量互异真随机素数组成。 - **高性能数据库索引结构优化**:像B+树这样的自平衡多路检索型数据表经常面临频繁更新带来的性能瓶颈问题,此时引入哈希映射辅助查询路径缩短便显得尤为重要。选取合适的散列函数参数组合往往涉及到寻找满足一定条件约束关系的一系列特殊数字集合,这正是区间筛所擅长之处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值