POJ 2773 Happy 2006

来源:互联网 发布:网络安全法 隐私数据 编辑:程序博客网 时间:2024/05/21 08:43

求与m互素的数中第k大的数是多少

首先,如果(a,m)=(a+k*m,m)

也就是说,从1开始,与m互素的数是可以分段的,每m个数分成一段,且每段里面有PHI(m)个数,那么,我们只要知道[1,m]这个区间的分布情况就行了,令base=(k-1)/PHI(m),k=(k-1)%PHI(m)+1,那么现在的base*n+f(k)就是我们要求的那个数,f(k)为[1,m]中与m互素的第k大的数

 

第一次写的时候超时了,原因是我把[1,m]中与m互素的数全部求出来了,但题目只要求第k大的数,我们其实可以从1开始枚举,枚举到第k个的时候直接返回结果,这样子勉强过,2500多ms

 

然后,想到,如果d=gcd(i,m)!=1,那么gcd(i+j*d,m)也不为1,这样的话,我们可以排除掉一些值,判断某些值是否与m互素时只要O(1)的时间,这样可以优化到1700ms左右

 

这说明,我们节省的计算gcd的时间是比较可观的,那么,是否可以进一步优化呢?答案是肯定的,我们可以用O(m)的时间预处理所有与m不是互素的数,然后用O(1)的时间判断[1,m]内某个数是否和m互素

 

我们在计算PHI(m)时,其实已经对m进行分解,求出了m的所有素因子,再想,所有与m不互素的数,都至少与m有一个公共素因子,于是,我们可以在每次找到一个m的素因子后,将它的整数倍标记,这样,后面枚举的时候就可以用O(1)的时间判断了,这样的话只要47ms,非常大的以一个优化

 

其实这题只要算出1000内的素数就可以了,设m=p1^a1*p2^a2*...*pn^an,如果存在pi>1000,pj>1000,m>10^6,如果pi>1000,ai>=2,m>10^6,所有只要求出1000内的素数就可以将m分解了

 

代码:

 

 

原创粉丝点击