我觉得我的还能再优化

发布时间:2022-09-26 23:50:54
贴主:想做嘉宜的小宝贝
热度:15
正在讨论:P3639 - 特别的数 题目传送门

想做嘉宜的小宝贝 2022-10-13

浅浅记录一下,这题如果单独对每个数都查找一下质因数的个数很显然是会超时的。

所以捏,不难想出这题是需要预处理打表的。如果连打表是什么意思都不知道的话这题可能不适合目前的你。

我们借助埃氏筛的思想,先有一个很大的数组,我们假设它叫做 num 。

埃氏筛的思路是什么呢,从2开始,把2的倍数都标记一遍(注意是不包括本身嗷),然后从3开始,把3的倍数都标记一遍,然后4,5.....

最后!剩下的没有标记的就是素数,是不是很神奇!

我们在这里也是同理,把num数组初始化全为0。然后从2开始,把2的倍数全部num[x]++,然后是3,然后4,5......

//用代码实现一下这个过程

```c++

for (int i = 2; i < MAXN; ++i) {

        for (int j = 2; j <MAXN && i*j<MAXN ; ++j) {

            num[i*j]++;

        }

    }

```

//这里的MAXN表示的数组最大长度

那么循环结束后这个num数组记录了什么,是不是记录了该下标所表示的数的因数个数。

我们回来再看一下题目,题目中找的是一个数m,并且这个数是由两个质数相乘得到的。

这说明了什么?是不是说明这个数的因数个数为2,并且这个数的这两个因数的因数个数为0?

而我们num正好记录的是因数个数。但是!我们怎么知道这个数的两个因数分别是谁?所以我们还需要一个额外的数组来存储这个数的两个因数之一。为什么不需要两个都存呢,因为已知这个罗少要求的数和他的一个因数,另一个因数是不是就是用这个数除以他的一个因数来得到呀。

我们假设另一个数组的名字叫做getnum,那么当num[i*j]++时,我们再把getnum[i*j]=i 或者j是不是就可以了。

那么假设我们读到了一个数m,如果这个数m的因数个数为2并且他的两个因数都是质数,这个数就是罗少需要的数。转换成编程语言就是 num[m] == 2 && num[getnum[m]] != 0 &&num[m / getnum[m]] != 0

是不是到现在就结束啦,收工了!

然而并不是的,当时比赛的时候我也以为到这里就结束了,等待我的就是AC了。然后很快的一发WA击垮了我。

那么究竟是哪里出错了呢,我们来看当m等于49这个情况。

这个情况下m是由7*7组成的,满足罗少的喜好吧,但是在我们这里却会出大问题。因为在我们的代码看来,49的因数就一个7啊,不满足我们的条件。所以我们的条件判断是有问题的,还需要再加一条判断:当m的因数个数为1个的时候并且这个数的因数是质数并且m=getnum[m] * getnum[m]。

转换成我们的代码语言就是num[m] == 1&& num[getnum[m]] != 0 && m == getnum[m] * getnum[m]。

到此,这题就真的结束啦!

(只是记录一下,尚未排版,非最终版)

(8)

想做嘉宜的小宝贝 2022-09-27

20220927002312_87b7cf.png

这里还可以再优化一下,可以把 num[getnum[m]] != 0 && m == getnum[m] * getnum[m] 删掉,大伙可以想想看为啥,这里就不解答了嗷。

(5)

Copyright 2016 - 2024 XUJC ACM Team
闽ICP备2020022076号-1