当前位置: 代码迷 >> 综合 >> 质数判断超详解--HihoCoder--1295--Eular质数筛法||Miller_Rabin算法
  详细解决方案

质数判断超详解--HihoCoder--1295--Eular质数筛法||Miller_Rabin算法

热度:62   发布时间:2023-12-12 06:10:27.0

问题描述:前驱质数查找--统计前缀和类似https://blog.csdn.net/queque_heiya/article/details/105931133

思路一:采取素数筛法,初始化求解,暴力统计;

1.优点在于可以初始化统计,解决多个输入的问题;2.缺点在于在n>=1e7+10以上,10s无法解决的;

代码如下:时间7953ms;

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define ll long long
using namespace std;
const ll maxa=1e6+10;
int dp[maxa];
bool prime(ll n){if(n==2)	return true;for(int i=2;i<=sqrt(n);i++)if(n%i==0)	return false;return true;
}
void init(){memset(dp,0,sizeof dp);dp[2]=1;for(int i=3;i<=maxa;i++){if(prime(i))	dp[i]+=dp[i-1]+1;else dp[i]=dp[i-1];}
}
int main(){ll n;init();scanf("%lld",&n);printf("%lld\n",dp[n]);return 0;
}
/*Sample Input
9
Sample Output
4*/ 

思路二:prime()+暴力统计;优缺点鉴于思路一和思路三之中;

代码如下:时间4985ms;O(n*sqrt(n));

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
bool prime(LL n){if(n==2)	return true;for(int i=2;i<=sqrt(n);i++)if(n%i==0)	return false;return true;
} 
int main(){LL n,ans=0;scanf("%lld",&n);for(LL i=2;i<=n;i++)if(prime(i))ans++;printf("%lld\n",ans);return 0;
}

思路三:Miller_Rabin算法+暴力统计;

1.优点在于所用时间低;2.缺点在于代码书写复杂,设计内容多;

代码如下:时间:3642ms; 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
LL mul_mod(LL a,LL b,LL mod){LL ret=0;while(b){if(b&1)    ret=ret+a;if(ret>=mod)	ret-=mod;a=a+a;if(a>=mod)	a-=mod;b>>=1;}return ret;
}
LL pow_mod(LL a,LL b,LL mod){LL ret=1;while(b){if(b&1)ret=mul_mod(ret,a,mod);a=mul_mod(a,a,mod);b>>=1;}return ret;
}
bool Miller_Rabin(LL n){//判断素数 LL u=n-1,pre,x;int i,j,k=0;if(n==2||n==3||n==5||n==7||n==11)	return true;if(n==1||(!(n%2))||(!(n%3))||(!(n%5))||(!(n%7))||(!(n%11))) returnfalse;//初始化判断素数 for(;!(u&1);k++,u>>=1);//按照要求转换形式 for(i=0;i<5;i++){x=rand()%(n-2)+2;//生成随机数 x=pow_mod(x,u,n);pre=x;for(j=0;j<k;j++){x=mul_mod(x,x,n);if(x==1&&pre!=1&&pre!=(n-1))//二次探测判断 return false;pre=x;}if(x!=1) return false;//用费马小定理判断 }return true;
}
int main(){LL n,ans=0;scanf("%lld",&n);for(LL i=2;i<=n;i++)if(Miller_Rabin(i))ans++;printf("%lld\n",ans);return 0;
}

 

  相关解决方案