[素数个数模板] HDU 5901 Count primes

题目链接:传送门

题目大意:给你一个 n(1 <= n <= 1e11),问1~n中素数个数

题目思路:(Meisell-Lehmer算法)

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 #define LL long long
 5 const int N = 5e6 + 2;
 6 bool np[N];
 7 int prime[N], pi[N];
 8 int getprime()
 9 {
10     int cnt = 0;
11     np[0] = np[1] = true;
12     pi[0] = pi[1] = 0;
13     for(int i = 2; i < N; ++i)
14     {
15         if(!np[i]) prime[++cnt] = i;
16         pi[i] = cnt;
17         for(int j = 1; j <= cnt && i * prime[j] < N; ++j)
18         {
19             np[i * prime[j]] = true;
20             if(i % prime[j] == 0)   break;
21         }
22     }
23     return cnt;
24 }
25 const int M = 7;
26 const int PM = 2 * 3 * 5 * 7 * 11 * 13 * 17;
27 int phi[PM + 1][M + 1], sz[M + 1];
28 void init()
29 {
30     getprime();
31     sz[0] = 1;
32     for(int i = 0; i <= PM; ++i)  phi[i][0] = i;
33     for(int i = 1; i <= M; ++i)
34     {
35         sz[i] = prime[i] * sz[i - 1];
36         for(int j = 1; j <= PM; ++j) phi[j][i] = phi[j][i - 1] - phi[j / prime[i]][i - 1];
37     }
38 }
39 int sqrt2(LL x)
40 {
41     LL r = (LL)sqrt(x - 0.1);
42     while(r * r <= x)   ++r;
43     return int(r - 1);
44 }
45 int sqrt3(LL x)
46 {
47     LL r = (LL)cbrt(x - 0.1);
48     while(r * r * r <= x)   ++r;
49     return int(r - 1);
50 }
51 LL getphi(LL x, int s)
52 {
53     if(s == 0)  return x;
54     if(s <= M)  return phi[x % sz[s]][s] + (x / sz[s]) * phi[sz[s]][s];
55     if(x <= prime[s]*prime[s])   return pi[x] - s + 1;
56     if(x <= prime[s]*prime[s]*prime[s] && x < N)
57     {
58         int s2x = pi[sqrt2(x)];
59         LL ans = pi[x] - (s2x + s - 2) * (s2x - s + 1) / 2;
60         for(int i = s + 1; i <= s2x; ++i) ans += pi[x / prime[i]];
61         return ans;
62     }
63     return getphi(x, s - 1) - getphi(x / prime[s], s - 1);
64 }
65 LL getpi(LL x)
66 {
67     if(x < N)   return pi[x];
68     LL ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;
69     for(int i = pi[sqrt3(x)] + 1, ed = pi[sqrt2(x)]; i <= ed; ++i) ans -= getpi(x / prime[i]) - i + 1;
70     return ans;
71 }
72 LL lehmer_pi(LL x)
73 {
74     if(x < N)   return pi[x];
75     int a = (int)lehmer_pi(sqrt2(sqrt2(x)));
76     int b = (int)lehmer_pi(sqrt2(x));
77     int c = (int)lehmer_pi(sqrt3(x));
78     LL sum = getphi(x, a) +(LL)(b + a - 2) * (b - a + 1) / 2;
79     for (int i = a + 1; i <= b; i++)
80     {
81         LL w = x / prime[i];
82         sum -= lehmer_pi(w);
83         if (i > c) continue;
84         LL lim = lehmer_pi(sqrt2(w));
85         for (int j = i; j <= lim; j++) sum -= lehmer_pi(w / prime[j]) - (j - 1);
86     }
87     return sum;
88 }
89 int main()
90 {
91     init();
92     LL n;
93     while(~scanf("%lld",&n))
94     {
95         printf("%lld\n",lehmer_pi(n));
96     }
97     return 0;
98 }  
时间: 2024-10-10 09:42:13

[素数个数模板] HDU 5901 Count primes的相关文章

hdu 5901 Count primes 素数计数模板

转自:http://blog.csdn.net/chaiwenjun000/article/details/52589457 计从1到n的素数个数 两个模板 时间复杂度O(n^(3/4)) 1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 ll f[340000],g[340000],n; 5 void init(){ 6 ll i,j,m; 7 for(m=1;m*m<=n;++m)f[

HDU 5901 Count primes (模板题)

题意:给求 1 - n 区间内的素数个数,n <= 1e11. 析:模板题. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstrin

hdu 5901 Count primes (2016沈阳网络赛)

原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5901 题意:输入n,输出n以内质数个数 模板题,模板我看不懂,只是存代码用. 官方题解链接:https://async.icpc-camp.org/d/560-2016 /************************************************************ 这个模板我一点都不会,代码是从codeforces上抄的,佚名 pi(i)表示i以内质数的个数 ******

HDU 5901 Count primes (1e11内的素数个数) -2016 ICPC沈阳赛区网络赛

题目链接 题意:求[1,n]有多少个素数,1<=n<=10^11.时限为6000ms. 官方题解:一个模板题, 具体方法参考wiki或者Four Divisors. 题解:给出两种代码. 第一种方法Meisell-Lehmer算法只需265ms. 第二种方法不能运行但是能AC,只需35行. 第一种: //Meisell-Lehmer #include<cstdio> #include<cmath> using namespace std; #define LL long

Hdu 5901 Count primes

求N以内素数的个数. N很大 模板题. #include<cstdio> #include<cmath> using namespace std; #define LL long long const int N = 5e6 + 2; bool np[N]; int prime[N], pi[N]; int getprime() { int cnt = 0; np[0] = np[1] = true; pi[0] = pi[1] = 0; for(int i = 2; i <

leetcode 204. Count Primes 找出素数的个数 ---------- java

Description: Count the number of prime numbers less than a non-negative number, n. 找出小于n的素数个数. 1.用最淳朴的算法果然超时了. public class Solution { public int countPrimes(int n) { if (n < 2){ return 0; } int result = 0; for (int i = 2; i < n; i++){ if (isPrimes(

LeetCode Count Primes 求素数个数

题意:给一个数n,返回小于n的素数个数. 思路: 1 class Solution { 2 public: 3 int countPrimes(int n) { 4 bool* isPrime =new bool[n] ; 5 6 memset(isPrime,1,n); 7 8 for(int i=2; i*i<n; i++) 9 { 10 if(!isPrime[i]) continue; 11 for(int j=i*i; j<n; j+=i) isPrime[j]=0; 12 } 13

leetcode 204. Count Primes(线性筛素数)

Description: Count the number of prime numbers less than a non-negative number, n. 题解:就是线性筛素数的模板题. class Solution { public: int countPrimes(int n) { int ans=0; vector<int>is_prime(n+1,1); for(int i=2;i<n;i++){ if(is_prime[i]){ ans++; for(int j=2*

HDU 5317 RGCDQ(素数个数 多校2015啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5317 Problem Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more and more interesting things about GCD. Today He comes up with Range Greatest Common Divisor Query (R