题目链接:点我~~
题意:求1e11内素数个数。
思路:Meisell-Lehmer的n^(2/3)方法,参考cf665F。
#include <bits/stdc++.h> using namespace std; #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef vector<int> VI; typedef long long LL; typedef pair<int,int> PII; typedef pair<double,double> PDD; const int mod=1e9+7; const double eps=1e-8; const int inf=0x3f3f3f3f; const double pi=acos(-1.0); //LL powmod(LL a,LL b) {LL res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} const int MAXN=1000010; #define MAX 1000010 #define sb(ar, i) (((ar[(i) >> 6]) |= (1 << (((i) >> 1) & 31)))) #define cb(ar, i) (((ar[(i) >> 6]) & (1 << (((i) >> 1) & 31)))) #define isprime(x) (( (x) && ((x)&1) && (!cb(ar, (x)))) || ((x) == 2)) LL dp[91][50010]; unsigned int ar[(10000010 >> 6) + 5] = {0}; int len = 0, pri[666666], cnt[1000010]; void solve() { sb(ar, 0), sb(ar, 1); for (int i = 3; (i * i) < MAXN; i++, i++) { if (!cb(ar, i)) { int k = i << 1; for (int j = (i * i); j < MAXN; j += k) { sb(ar, j); } } } for (int i = 1; i < MAXN; i++) { cnt[i] = cnt[i - 1]; if (isprime(i)) pri[len++] = i, cnt[i]++; } } void init() { solve(); for (int n = 0; n < 90; n++) { for (int m = 0; m < 50010; m++) { if (!n) dp[n][m] = m; else dp[n][m] = dp[n - 1][m] - dp[n - 1][m / pri[n - 1]]; } } } LL TT(LL m, int n) { if (n == 0) return m; if (pri[n - 1] >= m) return 1; if (m < 50010 && n < 90) return dp[n][m]; return TT(m, n - 1) - TT(m / pri[n - 1], n - 1); } LL Lehmer(LL m) { if (m < MAX) return cnt[m]; LL w, res = 0; int i, a, s, c, x, y; s = sqrt(0.9 + m), y = c = cbrt(0.9 + m); a = cnt[y], res = TT(m, a) + a - 1; for (i = a; pri[i] <= s; i++) res = res - Lehmer(m / pri[i]) + Lehmer(pri[i]) - 1; return res; } int main() { init(); LL n, res; while(~scanf("%lld",&n)) { printf("%lld\n",Lehmer(n)); } return 0; }
- 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
- 文章链接:http://www.carlstedt.cn/archives/1170 (转载时请注明本文出处及文章链接)
发表评论
快来吐槽一下吧!