爆炸快求1~n有多少素数
这个求一千亿以内的素数大约用6780ms
#include <stdio.h> #include <iostream> #include <string.h> #include <stdlib.h> #include <time.h> #include <math.h> using namespace std; __int64 *primarr, *v; __int64 q = 1, p = 1; void Out(__int64 a) //输出外挂 { if(a>9) Out(a/10); putchar(a%10+'0'); } __int64 Scan() //输入外挂 { __int64 res=0,ch,flag=0; if((ch=getchar())=='-') flag=1; else if(ch>='0'&&ch<='9') res=ch-'0'; while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0'; return flag?-res:res; } //π(n) __int64 pi(__int64 n, __int64 primarr[], __int64 len) { __int64 i = 0, mark = 0; for (i = len - 1; i > 0; i--) { if (primarr[i] < n) { mark = 1; break; } } if (mark) return i + 1; return 0; } //Φ(x,a) __int64 phi(__int64 x, __int64 a, __int64 m) { if (a == m) return (x / q) * p + v[x % q]; if (x < primarr[a - 1]) return 1; return phi(x, a - 1, m) - phi(x / primarr[a - 1], a - 1, m); } __int64 prime(__int64 n) { char *mark; __int64 mark_len; __int64 count = 0; __int64 i, j, m = 7; __int64 sum = 0, s = 0; __int64 len, len2, len3; mark_len = (n < 10000) ? 10002 : ((__int64 )exp(2.0 / 3 * log(n)) + 1); //筛选n^(2/3)或n内的素数 mark = (char *)malloc(sizeof(char) * mark_len); memset(mark, 0, sizeof(char) * mark_len); for (i = 2; i < (__int64 )sqrt(mark_len); i++) { if (mark[i]) continue; for (j = i + i; j < mark_len; j += i) mark[j] = 1; } mark[0] = mark[1] = 1; //统计素数数目 for (i = 0; i < mark_len; i++) if (!mark[i]) count++; //保存素数 primarr = (__int64 *)malloc(sizeof(__int64 ) * count); j = 0; for (i = 0; i < mark_len; i++) if (!mark[i]) primarr[j++] = i; if (n < 10000) return pi(n, primarr, count); //n^(1/3)内的素数数目 len = pi((__int64 )exp(1.0 / 3 * log(n)), primarr, count); //n^(1/2)内的素数数目 len2 = pi((__int64 )sqrt(n), primarr, count); //n^(2/3)内的素数数目 len3 = pi(mark_len - 1, primarr, count); //乘积个数 j = mark_len - 2; for (i = (__int64 )exp(1.0 / 3 * log(n)); i <= (__int64 )sqrt(n); i++) { if (!mark[i]) { while (i * j > n) { if (!mark[j]) s++; j--; } sum += s; } } free(mark); sum = (len2 - len) * len3 - sum; sum += (len * (len - 1) - len2 * (len2 - 1)) / 2; //欧拉函数 if (m > len) m = len; for (i = 0; i < m; i++) { q *= primarr[i]; p *= primarr[i] - 1; } v = (__int64 *)malloc(sizeof(__int64 ) * q); for (i = 0; i < q; i++) v[i] = i; for (i = 0; i < m; i++) for (j = q - 1; j >= 0; j--) v[j] -= v[j / primarr[i]]; sum = phi(n, len, m) - sum + len - 1; free(primarr); free(v); return sum; } int main() { __int64 n; //int h; ///clock_t start, end; //freopen("C:\\Users\\acer\\Desktop\\in.txt","r",stdin); //std::ios::sync_with_stdio(false); while(~scanf("%lld",&n)) { if(n==2) { printf("1\n"); continue; } //p=1; //q=1; //start = clock(); Out(prime(n+1)); printf("\n"); //end = clock() - start; //printf("用时%lfms\n",(double)end); } return 0; }
这个完全就是爆炸了
#include <bits/stdtr1c++.h> #define MAXN 100 // pre-calc max n for phi(m, n) #define MAXM 100010 // pre-calc max m for phi(m, n) #define MAXP 666666 // max primes counter #define MAX 10000010 // max prime #define clr(ar) memset(ar, 0, sizeof(ar)) #define read() freopen("lol.txt", "r", stdin) #define dbg(x) cout << #x << " = " << x << endl // compressed bool flag for sieve prime. (i >> 1) because even numbers are omitted. #define setbit(ar, i) (((ar[(i) >> 6]) |= (1 << (((i) >> 1) & 31)))) #define chkbit(ar, i) (((ar[(i) >> 6]) & (1 << (((i) >> 1) & 31)))) #define isprime(x) (( (x) && ((x)&1) && (!chkbit(ar, (x)))) || ((x) == 2)) using namespace std; namespace pcf{ long long dp[MAXN][MAXM]; unsigned int ar[(MAX >> 6) + 5] = {0}; int len = 0, primes[MAXP], counter[MAX]; void Sieve(){ setbit(ar, 0), setbit(ar, 1); for (int i = 3; (i * i) < MAX; i++, i++){ if (!chkbit(ar, i)){ int k = i << 1; for (int j = (i * i); j < MAX; j += k) setbit(ar, j); } } for (int i = 1; i < MAX; i++){ counter[i] = counter[i - 1]; if (isprime(i)) primes[len++] = i, counter[i]++; } } void init(){ Sieve(); for (int n = 0; n < MAXN; n++){ for (int m = 0; m < MAXM; m++){ if (!n) dp[n][m] = m; else dp[n][m] = dp[n - 1][m] - dp[n - 1][m / primes[n - 1]]; } } } long long phi(long long m, int n){ if (n == 0) return m; if (primes[n - 1] >= m) return 1; if (m < MAXM && n < MAXN) return dp[n][m]; return phi(m, n - 1) - phi(m / primes[n - 1], n - 1); } long long Lehmer(long long m){ if (m < MAX) return counter[m]; long long w, res = 0; int i, a, s, c, x, y; s = sqrt(0.9 + m), y = c = cbrt(0.9 + m); a = counter[y], res = phi(m, a) + a - 1; for (i = a; primes[i] <= s; i++) res = res - Lehmer(m / primes[i]) + Lehmer(primes[i]) - 1; return res; } } int main(){ pcf::init(); long long n, res; while (scanf("%lld", &n) != EOF){ printf("%lld\n", pcf::Lehmer(n)); } return 0; }
我每天都在努力,只是想证明我是认真的活着.