求10的10次方内素数的个数与素数和的模板

本文介绍了一种O(n^(3/4))复杂度的算法来计算指定范围内素数的数量及求和,并提供了完整的C++实现代码。该算法通过优化筛法减少不必要的计算,适用于大范围的素数计算任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll check(ll v, ll n, ll ndr, ll nv) {
    return v >= ndr ? (n / v - 1) : (nv - v);
}
ll primenum(ll n) // O(n^(3/4))
{
  ll r = (ll)sqrt(n);
  ll ndr = n / r;
  assert(r*r <= n && (r+1)*(r+1) > n);
  ll nv = r + ndr - 1;
  std::vector<ll> S(nv+1);
  std::vector<ll> V(nv+1);
  for(ll i=0;i<r;i++) {
    V[i] = n / (i+1);
  }
  for(ll i=r;i<nv;i++) {
    V[i] = V[i-1] - 1;
  }
  for(ll i = 0;i<nv;i++) {
    S[i] = V[i] - 1; //求素数个数
  }
  for(ll p=2;p<=r;p++) {
    if(S[nv-p] > S[nv-p+1]) {
      ll sp = S[nv-p+1]; // sum of primes smaller than p
      ll p2 = p*p;
      for(ll i=0;i<nv;i++) {
        if(V[i] >= p2) {
          S[i] -= 1LL  * (S[check(V[i] / p, n, ndr, nv)] - sp); //求素数个数
        }
        else break;
      }
    }
  }
  return S[0];
}
ll primesum(ll n) // O(n^(3/4))
{
  ll r = (ll)sqrt(n);
  ll ndr = n / r;
  assert(r*r <= n && (r+1)*(r+1) > n);
  ll nv = r + ndr - 1;
  std::vector<ll> S(nv+1);
  std::vector<ll> V(nv+1);
  for(ll i=0;i<r;i++) {
    V[i] = n / (i+1);
  }
  for(ll i=r;i<nv;i++) {
    V[i] = V[i-1] - 1;
  }
  for(ll i = 0;i<nv;i++) {
    S[i] = V[i] * ( V[i] + 1) / 2 - 1; //求素数和
  }
  for(ll p=2;p<=r;p++) { // p is prime 
    if(S[nv-p] > S[nv-p+1]) {
      ll sp = S[nv-p+1]; // sum of primes smaller than p
      ll p2 = p*p; 
      for(ll i=0;i<nv;i++) {
        if(V[i] >= p2) {
        S[i] -= p* (S[check(V[i] / p, n, ndr, nv)] - sp); //求素数和
        }
        else break;
      }
    }
  }
  return S[0];
}
int main(int argc, char const *argv[]) {
//  std::cout << primesum(1e6) << '\n';
  std::cout << primenum(1e10) << '\n';
  std::cout << primesum(23) << '\n';
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
  return 0;
}

注: 共三个函数:①check函数 ②primenum函数(返回素数个数)③primesum函数(返回n以内的素数和)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值