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 <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <tr1/unordered_map>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;
using namespace std :: tr1;

typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const LL LNF = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const int N = 1e6 + 5;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *Hex[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
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 < N; ++i){
        if(!np[i]) prime[++cnt] = i;
        pi[i] = cnt;
        for(int j = 1; j <= cnt && i * prime[j] < N; ++j){
            np[i * prime[j]] = true;
            if(i % prime[j] == 0)   break;
        }
    }
    return cnt;
}

const int M = 7;
const int PM = 2 * 3 * 5 * 7 * 11 * 13 * 17;
int phi[PM + 1][M + 1], sz[M + 1];
void init(){
    getprime();
    sz[0] = 1;
    for(int i = 0; i <= PM; ++i)  phi[i][0] = i;
    for(int i = 1; i <= M; ++i){
        sz[i] = prime[i] * sz[i - 1];
        for(int j = 1; j <= PM; ++j) phi[j][i] = phi[j][i - 1] - phi[j / prime[i]][i - 1];
    }
}

int sqrt2(LL x){
    LL r = (LL)sqrt(x - 0.1);
    while(r * r <= x)   ++r;
    return int(r - 1);
}

int sqrt3(LL x){
    LL r = (LL)cbrt(x - 0.1);
    while(r * r * r <= x)   ++r;
    return int(r - 1);
}

LL getphi(LL x, int s){
    if(s == 0)  return x;
    if(s <= M)  return phi[x % sz[s]][s] + (x / sz[s]) * phi[sz[s]][s];
    if(x <= prime[s]*prime[s])   return pi[x] - s + 1;
    if(x <= prime[s]*prime[s]*prime[s] && x < N){
        int s2x = pi[sqrt2(x)];
        LL ans = pi[x] - (s2x + s - 2) * (s2x - s + 1) / 2;
        for(int i = s + 1; i <= s2x; ++i) ans += pi[x / prime[i]];
        return ans;
    }
    return getphi(x, s - 1) - getphi(x / prime[s], s - 1);
}

LL getpi(LL x){
    if(x < N)   return pi[x];
    LL ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;
    for(int i = pi[sqrt3(x)] + 1, ed = pi[sqrt2(x)]; i <= ed; ++i) ans -= getpi(x / prime[i]) - i + 1;
    return ans;
}

LL lehmer_pi(LL x){
    if(x < N)   return pi[x];
    int a = (int)lehmer_pi(sqrt2(sqrt2(x)));
    int b = (int)lehmer_pi(sqrt2(x));
    int c = (int)lehmer_pi(sqrt3(x));
    LL sum = getphi(x, a) +(LL)(b + a - 2) * (b - a + 1) / 2;
    for (int i = a + 1; i <= b; i++){
        LL w = x / prime[i];
        sum -= lehmer_pi(w);
        if (i > c) continue;
        LL lim = lehmer_pi(sqrt2(w));
        for (int j = i; j <= lim; j++) sum -= lehmer_pi(w / prime[j]) - (j - 1);
    }
    return sum;
}

int main(){
    init();
    LL n;
    while(scanf("%I64d", &n) == 1){
        printf("%I64d\n", lehmer_pi(n));
    }
    return 0;
}
时间: 2024-10-11 02:41:15

HDU 5901 Count primes (模板题)的相关文章

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

求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 <

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 素数计数模板

转自: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

题目链接:传送门 题目大意:给你一个 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 {

POJ 3528 hdu 3662 三维凸包模板题

POJ 3528题:http://poj.org/problem?id=3528 HDU 3662:http://acm.hdu.edu.cn/showproblem.php?pid=3662 一个是求三维凸包面数,一个是求三维凸包表面积,都是很裸的. 贴代码: #include<stdio.h> #include<algorithm> #include<string.h> #include<math.h> #include<stdlib.h>

HDU 1251 Trie树模板题

1.HDU 1251 统计难题  Trie树模板题,或者map 2.总结:用C++过了,G++就爆内存.. 题意:查找给定前缀的单词数量. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b #define F(i,a,b

hdu 1711 KMP算法模板题

题意:给你两个串,问你第二个串是从第一个串的什么位置開始全然匹配的? kmp裸题,复杂度O(n+m). 当一个字符串以0为起始下标时.next[i]能够描写叙述为"不为自身的最大首尾反复子串长度". 当发生失配的情况下,j的新值next[j]取决于模式串中T[0 ~ j-1]中前缀和后缀相等部分的长度, 而且next[j]恰好等于这个最大长度. 防止超时.注意一些细节.. 另外:尽量少用strlen.变量记录下来使用比較好,用字符数组而不用string //KMP算法模板题 //hdu

HDU 2222 AC自动机模板题

题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 using namespace std; 5 char key[55]; 6 char des[1111111]; 7 struct node{ 8 node *fail; 9 node *next[26]; 10 int cnt;