NUIST OJ 1369 [2017 江苏科技大学 程序设计竞赛] B. Mr.Z 的四因子数 (数据加强版)
2017-11-30 22:01
811 查看
NUIST OJ 1369 [2017 江苏科技大学 程序设计竞赛] B. Mr.Z 的四因子数 (数据加强版)
NUIST OJ 1369 2017 江苏科技大学 程序设计竞赛 B MrZ 的四因子数 数据加强版题目
题目分析
求素数表及欧拉函数表
根据分解关系求数量
一个素数的三次方的情况
两个不相等的素数的乘积
整体代码与运行结果
随便说说
后记
题目
题目描述Mr.Z 是一多高超的数学大师,最喜欢研究的领域是数论,由于要经常做各类特殊的整数分布研充,所以他想麻烦你帮他解决一个问题。
考虑这样的一个数 K,它只含有四个因子,比如 10,它只有:1、2、5、10 这四个因子。我们将满足上述性质的数称为四因子数。
现在想请问你在区间 [ a, b ] 内有多少个四因子数。
输入描述
有多组测试数据,每组测试数据占一行。
每一行中,有两个用空格分隔的正整数 a 和 b。
a 和 b 均不超过 700000。
输出描述
对每组测试数据,输出一行答案。
样例输入
1 66666
1 666666
样例输出
15878
142481
题目分析
易得,四因子数可以为两个不相等的素数的乘积或者一个素数的三次方。因此,题目就划归成为求素数表和根据分解关系求数量
求素数表及欧拉函数表
此处贴出我之前写的快速求素数表的方法快速求素数表——埃氏筛法与欧拉筛法
详细就不再解释了
根据分解关系求数量
一个素数的三次方的情况
此处需要用到头文件#include<cmath>
这是为了使用下面的cbrt()函数
cbrt()函数的作用是开三次方。在欧拉函数中,可以直接求得在 1-T 的数字中,由一个素数的三次方组成四因子数的个数。
sum = pri[(int)cbrt(T)];
两个不相等的素数的乘积
两个不相等素数的乘积即使素数表中第1个开始,乘以第2个、第3个直到乘积即将大于 T 为止结束本次循环之后,从第2个素数开始重复执行上述循环,直到素数的大小即将大于 T 的二次开方。
for (int i = 0, m, n, t = sqrt(T);; i++) { m = pri[prime[i]]; n = pri[T / prime[i]]; if (prime[i]>t) break; else sum += n - m; }
整体代码与运行结果
/*code is far away from bug with the animal protecting
* ┏┓ ┏┓
*┏ ┛┻━━━┛┻┓
*┃ ┃
*┃ ━ ┃
*┃ ┳┛ ┗┳ ┃
*┃ ┃
*┃ ┻ ┃
*┃ ┃
*┗━┓ ┏━┛
* ┃ ┃神兽保佑
* ┃ ┃代码无BUG!
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*
*/
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define LENGTH 701005
int is_prime[LENGTH];//是否是素数
int prime[LENGTH];//素数表
int pri[LENGTH];//欧拉函数表
int get(int T) {
int sum;
sum = pri[(int)cbrt(T)];
for (int i = 0, m, n, t = sqrt(T);; i++) { m = pri[prime[i]]; n = pri[T / prime[i]]; if (prime[i]>t) break; else sum += n - m; }
return sum;
}
int main() {
int a, b;
memset(is_prime, 0, sizeof(int)*LENGTH);
memset(prime, 0, sizeof(int)*LENGTH);
memset(pri, 0, sizeof(int)*LENGTH);
for (int i = 2, t = 0, p = 0; i < LENGTH/2; i++) {
pri[i] = pri[i - 1];
if (is_prime[i] == 0)
{
prime[p++] = i;
pri[i]++;
}
for (int j = 0; j<p&&i*prime[j] <= LENGTH/2; j++) {
is_prime[i*prime[j]] = 1;
if (i%prime[j] == 0)
break;
}
}
while (cin >> a >> b) {
cout << get(b) - get(a - 1) << endl;
}
return 0;
}
似乎神兽在MarkDown里面出了点问题大家不要在意这个细节
结果如下
随便说说
在查询量很大的时候,这题目还可以用差分进行优化,以此达到高效多组查询的目的。然而偷懒的我就不写在这里。
后记
照例感谢 ThinkSpirit诸位大佬的支持附上大佬的题解
相关文章推荐
- NUIST OJ 1364 [2017 江苏科技大学 程序设计竞赛]D.重复成绩统计(改编) 【STL-map】
- 程序设计竞赛(acm)常用数据结构
- 程序设计竞赛默认首部代码
- 网络数据挖掘程序的设计
- ACM_程序设计竞赛:贪心算法:硬币问题
- 黑马程序员—Java基础加强 (基本数据的自动拆装箱及享元设计模式)
- 我想写程序#3 之 「简单地设计自己的数据表(Table)」
- 2017大学生程序设计邀请赛(华东师范大学)F. 丽娃河的狼人传说
- 2017计蒜之道程序设计大赛初赛第五场
- HashCrack程序数据及索引设计2
- 合理设计数据的格式能大幅提高效率和缩短程序代码
- 数据结构之程序设计
- 数据结构课程设计 题目1 活期储蓄程序
- 数据分析2017系统系统设计架构师的通过人数与通过率
- hrbust 软件与微电子学院 ACM 2017 级新人热身程序竞赛
- 程序设计竞赛网站集锦
- ACM_程序设计竞赛:贪心算法:字典最小序
- 编写一个学生和教师数据输入和显示程序,学生数据有编号,姓名,班号,和成绩,教师数据有编号,姓名,职称和部门。要求将编号,姓名输入显示设计成一个类person,并作为学生数据类t和教师数据操作类的基类
- 2017 程序设计实习之C++部分作业题汇总 - B:面向对象基础
- 2017 程序设计实习之C++部分作业题汇总 - E:多态与虚函数