jzxx.2120 半质数

该博客讨论了如何高效地解决寻找指定范围内半质数的问题。通过使用筛法预先生成素数表,然后枚举两个素数作为半质数的乘积,优化算法以适应大数据量和内存限制。博主提供了算法细节,包括限制两个乘数的范围以及根据乘积调整循环条件,确保在给定的限制内找到所有半质数。

质数又称素数,指在大于1的自然数中,只能被1和本身整除的数,也可定义为只有1和本身两个因数的数。而半质数的定义是这样的:若对于一个正整数N,恰好能够分解成两个质数的乘积,它就被称为半质数。比如,4=2*2,15=3*5都是半质数,12不是半质数,它的质因子分解式为12=2*2*3,分解出的质数共有3个,其中有2个质数2,1个质数3。
(jzxx. 2120 )
输入
输入数据仅有一行包含两个用空格隔开的正整数 S 和 E,其中 2≤S≤E<5000000。
输出
输出数据仅有一行包含一个整数表示在 S 到 E 之间共有多少个半质数。
样例输入
4 26
样例输出
10
提示
样例解释 
在 4 到 26 之间共有 10 个半质数,分别是 4, 6, 9, 10, 14, 15, 21, 22, 25, 26。
数据范围 
30%的数据满足:2≤S≤E<500
60%的数据满足:2≤S≤E<50000
100%的数据满足:2≤S≤E<5000000
来源/分类
常州市2014“信息与未来”夏令营选拔赛
题目地址http://oj.jzxx.net/problem.php?id=2120

【思路】
本题数据量大,而且限时1秒、限内存32M,32M空间大约能开整型数组800万左右(32×1024×1024/4=838万),直接暴力枚举、判断不可取,应考虑优化算法。容易想到的生成法,枚举两个乘数,只要乘积在给定区间内,就是一个解,最后输出解的个数即可。这个算法需要进行细节优化。
首先,筛法打素数表,大幅节省判素数的时间。其原理是,开一个布尔型数组pm[],其值表示下标i是否为素数,先赋初值为0,假定都是素数;那么如果2是素数,则2的所有倍数都不是素数,要划去,标记为1。
其次,限定两个乘数的数值范围。第1个乘数i是2 ~ E,再大则乘积大于E;第2个乘数j是i ~ E/2,此处限定j大于等于i,是为避免重复,有等于号是因为两个乘数可以相等;j最大是E/2,是因为有拆成2乘另一个素数的情况。
第三,根据乘积结果控制循环。如果比左端点S小,就继续枚举j;如果比右端点E大,则需要退出对j的枚举循环,因为再枚举也必定比E大。
 

#include <cstdio>
#include <cmath>
#define N 2500010 //2*250 0000=500 0000
bool pm[N];
void Prime() //素数打表
{
    pm[1] = 1; //1不是素数
    for (int i = 2; i <= N; i++)
    {
        if (pm[i] == 1)
            continue;                    //跳过已经标记为不是素数的数
        for (int j = 2; j * i <= N; j++) //枚举i的倍数
            pm[i * j] = 1;               //标记该数不是素数
    }
}
int SemiPrime(int st, int ed)
{
    int i, j, m, k = 0, t = sqrt(ed);
    for (i = 2; i <= t; ++i)
    {
        if (pm[i])
            continue; //寻找质数作为第1个乘数
        for (j = i; j <= ed / 2; ++j)
        {
            if (!pm[j]) //第2个乘数也是素数
            {
                m = i * j; //两素数乘积
                if (m < st)
                    continue; //比给定区间小则继续
                else if (m > ed)
                    break; //比给定区间大则不必再乘后面的数
                else
                    k++; //在区间内则计数
            }
        }
    }
    return k;
}
int main()
{
    int S, E;
    scanf("%d%d", &S, &E);
    Prime();
    printf("%d\n", SemiPrime(S, E));
    return 0;
}

 

以下是一个通用的示例代码,用于从网页提取活动信息(标题、日期、信息)并写入`jzxx.txt`文件。假设网页结构与之前的示例类似,活动信息包含在`li`标签内,且有对应的标题、日期和信息的`div`标签。 ```python import requests from bs4 import BeautifulSoup # 目标网页的 URL url = 'https://example.com/your_activity_page' # 请替换为实际的网页 URL r = requests.get(url) r.encoding = 'utf-8' hdlb = [] # 创建 BeautifulSoup 对象 soup = BeautifulSoup(r.text, "html.parser") # 找到包含所有活动的容器(这里假设是一个有特定类名的 div) activities_container = soup.find("div", class_="your-activity-container-class") # 请替换为实际的类名 if activities_container: # 找到所有的活动项(li 标签) activities_list = activities_container.find_all("li") # 遍历每个活动项 for activity in activities_list: # 提取活动标题 title_div = activity.find("div", class_="your-title-class") # 请替换为实际的类名 if title_div: hdbt = title_div.text.strip() else: hdbt = "" # 提取活动日期 date_div = activity.find("div", class_="your-date-class") # 请替换为实际的类名 if date_div: hdrq = date_div.text.strip() else: hdrq = "" # 提取活动信息 info_div = activity.find("div", class_="your-info-class") # 请替换为实际的类名 if info_div: hdxx = info_div.text.strip() else: hdxx = "" # 将活动信息作为子列表添加到 hdlb 中 hdlb.append([hdbt, hdrq, hdxx]) # 打开文件并写入活动信息 f1 = open("jzxx.txt", "w", encoding="utf-8") for xx in hdlb: f1.write("%".join(xx) + "\n") f1.close() ``` ### 注意事项 - 代码中的`https://example.com/your_activity_page`、`your-activity-container-class`、`your-title-class`、`your-date-class`和`your-info-class`需要根据实际网页的 URL 和 HTML 结构进行替换。 - 若网页存在反爬机制,可能需要添加请求头(如`User-Agent`)或使用代理等方法来绕过反爬。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值