筛质数
1. 朴素法
#include<iostream>
using namespace std;
bool st[10010];
int primes[10010];
int cnt=0;
void get_primes(int n)
{
st[1]=true; // 1不是质数标记
for(int i=2;i<=n;i++)
{
if(!st[i])
primes[++cnt]=i; //记录质数
for(int j=i+i;j<=n;j+=i)
{
st[j] = true ; // 数的倍数(为合数) 标记
}
}
}
int main()
{
int n;
cin>>n;
get_primes(n);
for(int i=1;i<=cnt;i++)
{
cout<<primes[i]<<' ';
}
return 0;
}
2. 埃氏筛法
算术基本定理可表述为:任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积。
由算术基本定理得到每个合数必定是某个比它小的质数的倍数,所以我们只需要从小到大将所有质数的倍数筛掉,剩下的必然全都是质数。
#include<iostream>
using namespace std;
bool aiprime[1100];
int prime[1100];
int cnt=0;
int aiprimes(int n)
{
for(int i=0;i<=n;i++) aiprime[i]=true;
for(int i=2;i<=n;i++)
{
if(aiprime[i])
{
for(int j=2*i;j<=n;j+=i)
aiprime[j]=false;
}
if(aiprime[i]) {
prime[cnt++]=i;
}
}
return cnt;
}
int main()
{
int n,k=0;
cin>>n;
k=aiprimes(n);
cout<<k<<endl;
for(int i=0;i<k;i++)
cout<<prime[i]<<' ';
return 0;
}
3. 欧式筛分
欧式筛法和埃氏筛法原理一样,但是欧式筛法解决了埃氏筛法会重复筛选质数而导致时间复杂度的增加
#include<iostream>
using namespace std;
bool a[100000001];
int b[20000010];
int cnt=0;
long long int n,m;
void olaprime(int n)
{
a[1]=1;// 1 不是质数 标记;
for(int i=2;i<=n;i++)
{
if(a[i]==0) b[++cnt]=i;
for(int j=1;j<=cnt;j++)
{
if(i*b[j]>n)break;
a[i*b[j]]=1; //标记合数即标记质数的倍数
if(i%b[j]==0) break;
}
}
/*for(int i=1;i<=n;i++)
{
if(a[i]==0)
cout<<i<<endl;
}
/*for(int i=1;i<=cnt;i++)
cout<<b[i]<<' '; */
}
int main()
{
cin>>n>>m;
olaprime(n);
for(int i=1;i<=m;i++)
{
int x;
cin>>x;
cout<<b[x]<<endl;
}
return 0;
}
快速幂
快速幂就是解决指数运算问题
例题 【模板】快速幂||取余运算
#include<iostream>
using namespace std;
long long fastpow(long long a,long long n)//a为底 n为指数
{
if(n==1)return a;
long long temp=fastpow(a,n/2);
if(n%2==1)return temp*temp*a;
else return temp*temp;
}
long long fastP(long long a,long long n,long long p)
{
long long ans=1;
while(n){ //8 4 2 1法
if(n&1)ans=ans*a%p;//ans*=a; //或运算 取模: ans=ans*a%100;
a=a*a%p; //a*=a; //取模 a=a*a%100
n>>=1; //右移符号
}
return ans;
}
int main()
{
long long n,m,p;
scanf("%ld%ld%ld",&n,&m,&p);
//cout<<fastpow(n,m);
cout<<n<<"^"<<m<<" mod "<<p<<'='<<fastP(n,m,p)%p;
return 0;
}
}