杂题1 素数

1、埃拉托斯特尼筛法

const int MAXN = 1000000; 
void Prime()  
{  
    for (int i=0; i<MAXN; i++) prime[i]=1;  //先把每个数都定义为合数
    prime[0]=prime[1]=0;  
    for (int i=2; i<MAXN; i++)  
    {  
        if (!prime[i]) continue;  //如果为0就跳过,说明是素数 
        for (int j=i*2; j<MAXN; j+=i) prime[j] = 0;  //将i的倍数标记为合数
        //筛去2的倍数4、6、8,筛去3的倍数... 
    }  
} 

2、欧拉筛

//O(n)的筛法,每个合数只被它的最小质因子筛一次
//每一次的外循环筛出i和找到的质数
int  maxn;
int prime[120000];//prime[0]记录当前为止找到的素数的个数,1~maxn存找到的素数
int visit[120000];//其值为0时是素数,1~maxn用来打表 
void Prime()
{
    memset(visit,0,sizeof(visit));
    memset(prime, 0,sizeof(prime));
    for (int i = 2; i <= maxn; i++)
    {
//        cout<<" i = "<<i<<endl;
        if (!visit[i])
        {
            prime[++prime[0]] = i;//记录素数的个数,同时存找到的素数
        }
        for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++)//遍历每一个已找到的素数并且素数的倍数小于等于maxn 
        {
//            cout<<"           j = "<<j<<" prime["<<j<<"]"<<" = "<<prime[j]<<" i*prime[j] = "<<i*prime[j]<<endl;
            visit[i*prime[j]] = 1;//这个素数的倍数是合数
            if (i % prime[j] == 0)//因为每个数只被它的最小质因子筛一次,在此之后的质数不用筛,以后会筛
            {
                break;
            }
        }
    }
}

3、Miller-Rabin判断法

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll qpow(ll x,ll y,ll p)//x^y mod p
{
    ll ans=1,m=x;
    while(y)
    {
        if(y&1)ans*=m;
        ans%=p;
        m*=m;
        m%=p;
        y>>=1;
    }
    return ans;
}
bool check(ll x,ll y,ll p)
{
    ll q=qpow(x,y,p);
    if(q!=1&&q!=p-1)return 0;
    if(q==p-1)return 1;
    if(q==1&&(y&1))return 1;
    return check(x,y>>1,p);
}
bool mil(ll x)
{
    if(x<=1)return 0;
    if(x==2||x==7||x==61||(check(2,x-1,x)&&check(7,x-1,x)&&check(61,x-1,x)))/*底数RP++*/return true;
    return 0;
}
int main()
{
    int n,m;
    ll k;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>k;
        if(mil(k))cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
    return 0;
}

由于暂时看不懂.....先搁在这

可以参考下https://www.cnblogs.com/bytebull/p/11179316.html

luoguP3912 素数个数

题目描述

1,2,⋯ ,N1,2,cdots,N1,2,,N 中素数的个数。

输入格式

一行一个整数 NNN。

输出格式

一行一个整数,表示素数的个数。

输入输出样例

输入 #1
10
输出 #1
4

说明/提示

对于 40% 的数据,1N10^6。

对于 80% 的数据,1N10^7。

对于 100% 的数据,1N10^8。

解题思路

类似埃拉托斯特尼筛法,稍微做点改进

#include<bits/stdc++.h>
using namespace std;
bool a[100000000];//其值为0是素数 
int main() {
    int n,i,j,s=0;
    cin>>n;
    memset(a,0,sizeof(a));
    s=n-1;//去1 
    for(i=2; i*i<=n; i++) {
        if(a[i]==0)
            for(j=i*2; j<=n; j+=i) 
                if(a[j]==0) {//j必为合数,则去合数 
                    cout<<" i = "<<i<<" j = "<<j<<endl; 
                    a[j]=1;
                    s--;
                }
    }
    cout<<s;
  return 0; }

P1835 素数密度

题目描述

给定区间[L,R](L≤R≤2147483647,R-L≤1000000),请计算区间中素数的个数。

输入格式

两个数L和R。

输出格式

一行,区间中素数的个数。

输入输出样例

输入 #1
2 11
输出 #1
5

解题思路

看数据范围用简单筛法明显不行,不过呢L~R的范围很小

只要筛掉√2147483647内所有质数,然后用这其中的质数筛[l,r]内的数

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1000000;
int l , r;

int prime[maxn] , cnt=0 , tot=0;//cnt为质因子个数,tot为答案
bool vis[maxn];
bool ans[maxn];

void Euler() {
    for(int i = 2 ; i <= 50000 ; ++ i) {
        if(!vis[i]) {
            prime[++cnt] = i;
            for(int j = i + i ; j <= 50000 ; j += i) {
                vis[j] = 1;
            }
        }
    }
}
int _max(int a , int b) {
    return a > b ?  a : b;
}

signed main () {//因为前面 #define int long long了,这里int = signed int = signed
    Euler();
    cin>>l>>r;
    for(int i = 1 ; i <= cnt ;  i++) {
        for(int j = _max( 2 , (l - 1)/prime[i] + 1) * prime[i] ; j <= r ; j += prime[i]) 
            if(j - l >= 0) ans[j - l]=1;//等于1为合数
        }
        for(int i = 0 ; i <= r - l ;  i++)
            if(!ans[i]) tot ++;
        cout<<tot;
        return 0;
    }

P3383 【模板】线性筛素数

题目背景

本题已更新,从判断素数改为了查询第 kkk 小的素数
提示:如果你使用 cin 来读入,建议使用 std::ios::sync_with_stdio(0) 来加速。

题目描述

如题,给定一个范围 n,有 q 个询问,每次输出第 k 小的素数。

输入格式

第一行包含两个正整数 n,q分别表示查询的范围和查询的个数。

接下来 q行每行一个正整数 k,表示查询第 k小的素数。

输出格式

输出 q 行,每行一个正整数表示答案。

输入输出样例

输入 #1
100 5
1
2
3
4
5
输出 #1
2
3
5
7
11

说明/提示

【数据范围】
对于 100% 的数据,n=108n = 10^8n=108,1≤q≤10^6,保证查询的素数不大于 n

Data by NaCly_Fish.

解题思路

 用欧拉筛可以,但要注意数组的大小

#include<bits/stdc++.h>
using namespace std;
int prime[6000010];
bool visit[100000010];//1为素数 
void getPrime(int  maxn)
{
    memset(visit,1,sizeof(visit));
    memset(prime,0,sizeof(prime));
    visit[1]=0;
    for (int i = 2; i <= maxn; i++)
    {

        if (visit[i])
        {
            prime[++prime[0]] = i;
        }
        for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++)
        {

            visit[i*prime[j]] = 0;
            if (i % prime[j] == 0)
            {
                break;
            }
        }
    }
}
int main(){
    int n,k,maxn;
    cin>>maxn>>n;
    getPrime(maxn);
    for(int i=1; i<=n; i++){
        cin>>k;
        cout<<prime[k]<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/rakanXayan/p/13406408.html