首页 > 其他分享 >洛谷题单指南-数学基础问题-P1835 素数密度

洛谷题单指南-数学基础问题-P1835 素数密度

时间:2024-04-11 13:11:06浏览次数:25  
标签:标记 int 洛谷题 合数 枚举 素数 P1835 primes

原题链接:https://www.luogu.com.cn/problem/P1835

题意解读:要计算L-R范围内素数的个数。

解题思路:

直接对L~R的每个数判断素数肯定不可取,因为L、R的范围较大。

既然要计算素数的个数,那么可以把其中的合数标记出来即可。

如何标记合数?

可以借助于筛素数的算法思想,枚举每一个素数,然后把素数的2/3/4....n倍,且乘以倍数后在L~R范围内的数标记成合数,最后计算素数的个数即可。

问题在于,枚举每一个素数,这个最大的素数到多少合适?会不会超时?

如果合数最大是x,那么素数最多只要枚举到sqrt(x),就可以把所有合数都标记到。

因此,我们要枚举的素数最大在10^5内即可,放大一点,我们可以先筛出10^6范围内的所有素数,再枚举倍数,标记L~R范围内的合数。

枚举倍数从多少开始,到多少结束呢?

给定一个素数primes[i],倍数j起始点肯定是j * primes[i]接近l,倍数j的结束点肯定是j * primes[i]解决r,这样枚举次数最少

因此起点start = l / primes[i],终点end = r / primes[i]即可。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5;

int primes[N], cnt;
bool flag[N];
int l, r, c;
int h[N]; //标记出l~r之间的合数

int main()
{
    cin >> l >> r;
    if(l == 1) l++; //排除1的影响

    //筛2~1000000质数
    for(int i = 2; i <= 1000000; i++)
    {
        if(!flag[i])
        {
            primes[++cnt] = i;
            for(int j = i + i; j <= 1000000; j += i)
            {
                flag[j] = true;
            }
        }
    }

    for(int i = 1; i <= cnt; i++) //枚举每一个素数,再枚举倍数,使得素数*倍数在l~r范围内,则标记为合数
    {
        int start = l / primes[i]; //筛出l-r范围内的合数,也就是素数的倍数从l/primes[i]开始
        int end = r / primes[i]; //倍数到r/primes[i]截止
        if(start <= 1) start = 2; //起始至少从2倍开始
        if(end <= 1) break; //如果截止倍数不到2倍,则不可能筛出合数,后面的素数更大,end更小,提前退出
        for(int j = start; j <= end; j++)
        { 
            if(j * primes[i] >= l)
            {
                h[j * primes[i] - l] = 1; //标记l~r之间的合数,-l防止溢出
            } 
        }
    }
    
    int ans = r - l + 1;
    for(int i = 0; i <= r - l; i++)
    {
        if(h[i]) ans--;
    }
    cout << ans;

    return 0;
}

 

标签:标记,int,洛谷题,合数,枚举,素数,P1835,primes
From: https://www.cnblogs.com/jcwy/p/18128859

相关文章

  • 信息学奥赛一本通:1403:素数对
    【题目描述】两个相差为2的素数称为素数对,如5和7,17和19等,本题目要求找出所有两个数均不大于n的素数对。【输入】一个正整数n(1≤n≤10000)。【输出】所有小于等于n的素数对。每对素数对输出一行,中间用单个空格隔开。若没有找到任何素数对,输出empty。【输入样例】......
  • 洛谷题单指南-数学基础问题-P3383 【模板】线性筛素数
    原题链接:https://www.luogu.com.cn/problem/P3383题意解读:素数筛模版题。解题思路:素数筛介绍所谓素数(质数),是指除了1和它本身以外不再有其他因数的自然数,一般用试除法判断素数(时间复杂度:O(sqrt(n))):boolisprime(intx){if(x<=1)returnfalse;for(inti=2;i*......
  • 洛谷题单指南-数学基础问题-P2926 [USACO08DEC] Patting Heads S
    原题链接:https://www.luogu.com.cn/problem/P2926题意解读:有n个数,计算每个数能整除其他数的个数。解题思路:a[100005]记录所有的数,h[1000005]记录所有数的个数,cnt[1000005]记录所有数能整除其他数的个数只需要读入a数组,同时更新h[a[i]]++再依次从小到大遍历h的下标每一个数i,如......
  • 洛谷题单指南-数学基础问题-P2638 安全系统
    原题链接:https://www.luogu.com.cn/problem/P2638题意解读:把a个红球、b个黑球放入n个盒子,求所有的方法。解题思路:盒子中可以放也可以不放,可以放任意个,因此,题目可以转化为将i个红球(0<=i<=a),j个黑球(0<=j<=b)放入n个盒子的方案数之和,设f(n,i,j)表示将一个红球、j个黑球放入n......
  • 洛谷题单指南-数学基础问题-P3913 车的攻击
    原题链接:https://www.luogu.com.cn/problem/P3913题意解读:车所在的行、列一共有多个个格子。解题思路:假设3*3的棋盘,有三个车分析得知,三个车覆盖了第1、2两行,第2、3两列,覆盖的格子数用公式计算就是2*3+2*3-2*2=8也就是两行格子数加两列格子数再减去交叉点。因此......
  • 洛谷题单指南-数学基础问题-P2789 直线交点数
    原题链接:https://www.luogu.com.cn/problem/P2789题意解读:n条直线可以形成不同交点数的方案数。解题思路:对于n=1、2、3、4的情况进行模拟:n=1时,有1种不同的交点数n=2时,有2种不同的交点数n=3时,有3种不同的交点数n=4时,有5种不同的交点数对n=4的情况,分情况讨......
  • 洛谷B3840 [GESP202306 二级] 找素数
    这道题让我们找A 和 B 之间(包括 A 和 B)有多少个素数。#include<bits/stdc++.h>usingnamespacestd;boolisprime(intn){if(n==0||n==1)returnfalse;for(inti=2;i*i<=n;i++){if(n%i==0)returnfalse;}returntrue;}intmain(){......
  • 洛谷题单指南-数学基础问题-P1866 编号
    原题链接:https://www.luogu.com.cn/problem/P1866题意解读:N个整数M1~Mn,对每个整数Mi,选取1~Mi之间的一个数,使得N个数都不一样的选法。解题思路:将M1~Mn由小到大排序,第1个的选法有M1种第2个的选法有M2-1种第3个的选法有M3-2种......第n个选法有Mn-n+1种全部相乘取模即可。......
  • 洛谷题单指南-数学基础问题-P1017 [NOIP2000 提高组] 进制转换
    原题链接:https://www.luogu.com.cn/problem/P1017题意解读:负进制数的转换。解题思路:下面给出两种思路1、枚举法从数据范围来看,∣n∣≤37336,因此,可以对该r进制的数进行枚举,每一次枚举,都计算r进制数对应的十进制数是否和n相等,相等则输出该r进制数。主要问题就是要解决r进制......
  • 洛谷题单指南-数学基础问题-P1100 高低位交换
    原题链接:https://www.luogu.com.cn/problem/P1100题意解读:将32位二进制数的高低16位交换位置。解题思路:给定无符号整数a,假设二进制高16为h,低16位为l,即a表示为hl,a>>16得到0h,a<<16得到l0,两者相加即得到lh,交换完毕。需要注意的是,无符号整数的表示是unsignedint,如果是int,......