Ignatius 喜欢收集蝴蝶标本和邮票,但是Eddy的爱好很特别,他对数字比较感兴趣,他曾经一度沉迷于素数,而现在他对于一些新的特殊数比较有兴趣。
这些特殊数是这样的:这些数都能表示成M^K,M和K是正整数且K>1。
正当他再度沉迷的时候,他发现不知道什么时候才能知道这样的数字的数量,因此他又求助于你这位聪明的程序员,请你帮他用程序解决这个问题。
为了简化,问题是这样的:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K(K>1)的数。
Input
本题有多组测试数据,每组包含一个整数N,1<=N<=1000000000000000000(10^18).
Output
对于每组输入,请输出在在1到N之间形式如M^K的数的总数。
每组输出占一行。
Sample Input
10
36
1000000000000000000
Sample Output
4
9
1001003332
哎,一开始学容斥,并不知道怎么用上去,代码写起来好写,但是思路难啊。
下面开始分析:
题目意思:给你一个n,求出1-n里面,构成M^K(K>1)的数,比如1-4里面有1,4两个,1一定可以。
然后我们就去看数据范围了,1e18,很大,不可能枚举。
接着我就想,能不能分一下类,按2^k, 3^k, 4^k.......,这种,但是一想,1e18开方也还有1e9,这样分类不行
随后我就按照指数来分类,指数相同归为一类,例如(2^2, 3^2, 4^2....)归为一类,(2^3, 3^3, 4^3)归为一类,一次类推。
而且,这样分类还可以算出这一类有多少个数, 直接一个公式就行了,就是开k次方,然后-1,因为是从2开始的
某一类的个数
其中n就是n,k是幂次数,比如n为8时,x^2 这一类有3个。
其实这个特别好推。
重要的是下面的: 去重
我们分析一下,如果不去重,只需要一直开方,直到不能开为止,然后答案累加,这样复杂度并不高,1e18次最多开60次方就没了,因为2^60=1e18,所以时间根本不用担心。
那么怎么去重呢,拿样例36来说,我们先列举出来
指数为2: 2^2 3^2 4^2 5^2 6^2
指数为3: 2^3 3^3
指数为4: 2^4
指数为5: 2^5
后面就没了
我们可以看到16这个数重复了,4^2 = 16, 2^4 = 16
这是因为指数4本来就是2的倍数,2^4 = ( 2^2 )^2
那如果我们指数只枚举质数,是不是就能避免这种情况了,而且又可以减小计算量
但是,稍微再枚举一下,又能发现问题,
像 27^2这种 27^2 = ( 3*3*3 )^2 = 3^(3*2) = 3^6 = 9^3
你虽然避免了3^6,但是还有9^3会重复。
这时候就是最难点了,需要用到容斥,个人感觉在这个最后一点上不好想
27^2 和 9^3之所以会重复,是因为它们都有一个6,就是都能凑出指数6,那么我们减去指数6所得到的个数,就是答案了。
再自己一个样例
n = 729
729 = 27^2 = 3^6
指数为2: 2^2 3^2 4^2 5^2 6^2 7^2 8^2 9^2............................27^2
指数为3: 2^3 3^3 4^3 5^3 6^3 7^3 8^3 9^3
指数为5: 2^5
指数为7: 2^7
后面没有了
这里,我们就挑指数为2和指数为3的两类进行分析,看如何去除重复
我们首先要知道,指数为2和3的,重复的数一定可以构成指数为6的数
有 8^2 和 4^3是重复的
然后我们用n算出指数为6的个数,是1个,那么在算指数为2和3时,先+指数为2的,在+指数为3的,最后--指数为6的,这就用到了容斥原理。
所以我们开始设计算法:
①首先,我们把n的质指数求出来,质指数就是指数为质数,一个循环就可以搞定,而且非常快,几下就没了,前面分析过,就是一直开方,开到不能开为止,那么我们就把指数记录了下来。
②指数记录下来了,就要用容斥了,个人习惯用dfs,简洁一些,这时候我们还需要设计一个函数,给你一个指数值,你能算出这个符合这个指数的答案有多少个
需要注意一点,如果用dfs写,需要加一个条件,就是因子乘积小于60,不然就会超时,因为一个很大的数得出来的指数还是挺多的,指数组合在一起也挺多,但是很多组合都没有用,因为2^60 > 1e18,或者你加一个条件,因子最多选3个,不能选多了
#include
#include
#include
#include
#include
#include
#include
#include
#include