SCUT - 142 - 第n个素数
但是洲阁筛打表还是超时了,打的表不够长吧,在51nod上面要跑5s。要是快10倍得要密1000倍,根本打不出来(时间意义)。
暴力check要找的质数是不是要的那个。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAXN = 7500000;
int n;
int f[MAXN + 5], p[MAXN + 5];
bool np[MAXN + 5];
ll g(ll n, int m) {
if(!m)
return n;
if(m == 1)
return n - n / 2;
if(n <= MAXN) {
if(f[n] <= m)
return 1;
if(f[(int)sqrt(n)] <= m)
return f[n] - m + 1;
}
ll res = g(n, m - 1) - g(n / p[m], m - 1);
return res;
}
bool pan(ll x) {
ll y = sqrt(x);
return f[y] + g(x, f[y]) - 1 >= n;
}
void init() {
for(int i = 2; i <= MAXN; ++i) {
if(!np[i])
p[++p[0]] = i;
for(int j = 1, t; j <= p[0] && (t = p[j] * i) <= MAXN; ++j) {
np[t] = 1;
if(i % p[j] == 0)
break;
}
}
for(int i = 2; i <= MAXN; ++i)
f[i] = f[i - 1] + (np[i] == 0);
}
ll pcount[] = {
373587883,
776531401,
1190494759,
1611623773,
2038074743,
2468776129,
2902958801,
3340200037,
3780008329,
4222234741,
4666527007,
5112733757,
5560695863,
6010236857,
6461335109,
6913774603,
7367575799,
7822624247,
8278737359,
8736028057,
9194418049,
9653704481,
10113958157,
10575209467,
11037271757,
11500205947,
11963902331,
12428375423,
12893587657,
13359555403,
13826206699,
14293566641,
14761538761,
15230122499,
15699342107,
16169207209,
16639648327,
17110593779,
17582163853,
18054236957,
18526876243,
18999999247,
19473535801,
19947663787,
20422213579,
20897216723,
21372698029,
21848603809,
22325014259,
22801763489
};
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out", "w", stdout);
#endif // Yinku
init();
while(~scanf("%d", &n)) {
int px = n / (int)(2e7);
ll l = px == 0 ? 1 : pcount[px - 1], r = pcount[px], mid;
//cout << "l=" << l << " r=" << r << endl;
while(l < r) {
mid = (l + r) / 2;
if(pan(mid))
r = mid;
else
l = mid + 1;
}
printf("%lld\n", l);
}
}
下面的好迷惑啊;
#include<iostream>
#include<cmath>
#include<assert.h>
using namespace std;
typedef long long LINT;
LINT a,b,goal,n;
int mark[160000],prime[160000],e,bl[10000005];
LINT pn(int n)
{
LINT s=LINT(n*(log(n)+log(log(n))-1)+n*(log(log(n))-2)/log(n)-6.0*n/1000.0);
return s<=1?1:s;
}
inline LINT V2IDX(LINT v, LINT N, LINT Ndr, LINT nv) {
return v >= Ndr ? (N/v - 1) : (nv - v);
}
LINT primesum(LINT N) {
LINT *S;
LINT *V;
LINT r = (LINT)sqrt(N);
LINT Ndr = N/r;
assert(r*r <= N and (r+1)*(r+1) > N);
LINT nv = r + Ndr - 1;
V = new LINT[nv];
S = new LINT[nv];
for (LINT i=0; i<r; i++) {
V[i] = N/(i+1);
}
for (LINT i=r; i<nv; i++) {
V[i] = V[i-1] - 1;
}
for (LINT i=0; i<nv; i++) {
//S[i] = V[i] * (V[i] + 1) / 2 - 1;若求素数和,使用此处
S[i]=V[i] - 1;
//若求素数个数使用此处
}
for (LINT p=2; p<=r; p++) {
if (S[nv-p] > S[nv-p+1]) {
LINT sp = S[nv-p+1];
LINT p2 = p*p;
for (LINT i=0; i<nv; i++) {
if (V[i] >= p2) {
//S[i] -= p* (S[V2IDX(V[i]/p, N, Ndr, nv)] - sp);若求素数和,使用此处
S[i] -= 1* (S[V2IDX(V[i]/p, N, Ndr, nv)] - sp);
//若求素数个数,使用此处
} else {
break;
}
}
}
}
return S[0];
}
int main()
{
cin>>n;
a=pn(n);
if(a%2&&a>1)a=a-1;//防止预估值本身就是素数的情况,刚开始被这里坑了3个test
b=a+7000000;
goal=n-primesum(a);
for(int i=2;i<=160000;i++)
{
if(!mark[i])
{
prime[++e]=i;
for(LINT j=(LINT)i*i;j<=160000;j+=i)
{
mark[j]=1;
}
}
}
LINT xxx,c;
for(int i=1;i<=e;i++)
{
xxx=(LINT)ceil(1.0*a/prime[i]);
if(xxx==1) xxx++;
for(LINT j=xxx;(c=j*prime[i])<b;j++)
{
bl[c-a]=1;
}
}
int ans=0;
c=b-a;
if(a==1) ans--;
for(int i=0;i<c;i++)
{
if(!bl[i]) ans++;
if(ans==goal)
{
cout<<i+a<<endl;
break;
}
}
return 0;
}
Meisell-Lehmer算法 计算2~n之间的素数的个数然后二分就可以了。
bool np[maxn];
int prime[maxn],pi[maxn];
int getprime()
{
int cnt=0;
np[0]=np[1]=true;
pi[0]=pi[1]=0;
for(int i=2; i<maxn; ++i)
{
if(!np[i]) prime[++cnt]=i;
pi[i]=cnt;
for(int j=1; j<=cnt&&i*prime[j]<maxn; ++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<maxn)
{
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<maxn) 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<maxn) 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;
}
SCUT - 142 - 第n个素数的更多相关文章
- Java程序员面试题集(136-150)(转)
转:http://blog.csdn.net/jackfrued/article/details/17740651 Java程序员面试题集(136-150) 摘要:这一部分主要是数据结构和算法相关的面 ...
- Java面试题集(136-150)
摘要:目,尽管仅仅有15道题目.可是包括的信息量还是非常大的,非常多题目背后的解题思路和算法是非常值得玩味的. 136.给出以下的二叉树先序.中序.后序遍历的序列? 答:先序序列:ABDEGHCF.中 ...
- AtCoder Beginner Contest 142【D题】【判断素数的模板+求一个数的因子的模板】
D - Disjoint Set of Common Divisors Problem Statement Given are positive integers AA and BB. Let us ...
- WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化
WPF中的常用布局 一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...
- Help Hanzo (素数筛+区间枚举)
Help Hanzo 题意:求a~b间素数个数(1 ≤ a ≤ b < 231, b - a ≤ 100000). (全题在文末) 题解: a~b枚举必定TLE,普通打表MLE,真是头疼 ...
- Java 素数 prime numbers-LeetCode 204
Description: Count the number of prime numbers less than a non-negative number, n click to show more ...
- 求解第N个素数
任务 求解第 10,0000.100,0000.1000,0000 ... 个素数(要求精确解). 想法 Sieve of Eratosthenes 学习初等数论的时候曾经学过埃拉托斯特尼筛法(Sie ...
- 使用BitArray判断素数
首先显示1024范围内的所有素数,然后显示输入的数是否是素数.1024 是代码中计算的素数的范围,可以修改.计算平方根,是为了确定一个基数的范围.1024的平方根是32,两个超过32 的数相乘,肯定大 ...
- 查找素数Eratosthenes筛法的mpi程序
思路: 只保留奇数 (1)由输入的整数n确定存储奇数(不包括1)的数组大小: n=(n%2==0)?(n/2-1):((n-1)/2);//n为存储奇数的数组大小,不包括基数1 (2)由数组大小n.进 ...
随机推荐
- Django框架架构总览
Django框架架构总览 理解Django是如何运作的 条目创建于 2013-08-14 1464 views 服务器君一共花费 15.204 ms 进行了 4 次数据库查询,努力地为 ...
- JS 图片转blob 转base64
//转换为blob有跨域限制 var loadImageToBlob = function (url, callback) { if (!url || !callback) return false; ...
- 面试题常考&必考之--js中的数组去重和字符串去重
1.引入:首先得知道数组没有可以直接去重的方法,即直接[].unique()是不支持的, 会报“Uncaught TypeError: [].unique is not a function”错误, ...
- 七夕-心形表白-简单css代码
今天你要和谁过? 今天你要怎么过?? 今天去哪里吃??? 公司的三连问,对于一些单身狗有点招架不住啊. 在此送上一个薄礼,来安慰下受伤的心灵... 确定是安慰不是连环打击嘛..... 回答:确定! 来 ...
- Ubuntu 16.04下使用docker部署Redis主从复制
(以下docker相关的命令,需要在root用户环境下或通过sudo提升权限来进行操作.) 1.拉取Redis镜像到本地 docker pull redis 2. 准备Redis主从配置文件 Redi ...
- php日志托管给apache处理
php.ini配置: log_errors = On;不显示错误display_startup_errors = Offdisplay_errors = Off ;除了notice级别错误外,报告所有 ...
- 深入理解Spring(一):初识Spring
深入理解Spring(一):初识Spring 一. Spring介绍 Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnso ...
- 阿里云CentOS 7.3安装Redis详细步骤
############ 准备 ############### 从Redis官网下载Linux redis3.2.6版本,我下载的redis-3.2.6.tar.gz(目前最新稳定版),下载到/u ...
- What is the difference between Kill and Kill -9 command in Unix?
w difference kill -9 pid and kill pid command - Ask Ubuntu https://askubuntu.com/questions/791841/d ...
- tar命令: 解压到指定的目录, 解压并删除原tar文件
-f: 置顶文件名, 后面不能再跟其他选项字母了,必须是文件名, 但是再在这个后面又可以跟 -? 选项: -C: 指定解压到的目的目录 不是-c, 小写的-c是创建. -p保留原来文件的属性. tar ...