快速判断互质——浅析
2008-04-09 20:15
316 查看
这两天碰到一个问题,给定一个范围[1..n], 以及任意数m(1<m<=n), 统计给定域内与m互质的自然数的个数.
我们知道判断两个数互质充分必要条件是,两个数最大公约数=1, 这样,我们只需枚举i(1<=i<=n), 求gcd(i,m)即可,
辗转相除求gcd(i, m) 时间复杂度为logm+logi, 加上枚举时间,复杂度就为为 n*logm+logn!
若问题仅求一次m,近乎线性时间,是不错解决方案;但如果,如此取值m,比如在[1...n]中随即选取k个数,求每个
数在[1..n]中互质的个数,那么问题复杂度就变成O(k*n)了, 若n=50000, k=10000(即5个数中选取1个), 时间近乎数
十秒,这将不可忍受。
另法,快速求得[1..n]中与m不互素的个数res, 则n-res...
费费定理: 若整数i与m不互素,则m所有质因子中,至少一个也是i的质因子
步骤一:分解m求其质因子
方法,枚举[2..sqrt(m')]试除m';这里m'初始值m,每次枚举到一个质因子,便除去m'中所有此因子,
因此平均时间远小于sqrt(m), 但最坏情况下仍使sqrt(m), 可以做个优化,预处理[1..n]生成素数表(n=50000, 素数约5000),
筛选法求素数表时间O(3*n),然后直接拿生成的素数试除。
步骤二:求不互质个数
假设m分解后,质因子为p[pCnt], 那么[1...n]中包含这些质因子的数目为:
公式: 若pCnt=3,则
n/p[1]+n/p[2]+n/p[3]-n/(p[1]*p[2])-n/(p[1]*p[3])-n/(p[2]*p[3])+n/(p[1]*p[2]*p[3])
忘了这个叫什么来着,似乎是鸽巢定理的扩展吧。
其实pCnt值非常小,若n=50000, 则pCnt<7, 因为 2*3*5*7*11*13*17 >> 50000
这样,我们就可以简单深搜一下,计算上面公式的值,dfs时间 pCnt*2^pCnt (=384, n=50000时)
如此,总时间为O(k*t) t=sqrt(m)+pCnt*2^pCnt (t<600,n=50000时) 近乎于n无关,
因此,即使n=50000, k=10000, 计算复杂度也不超10^7,1s内, 实际上本机运行,不过几十ms.
至此,问题得到解决,从数十s到几十ms。
应该有更好的算法,期待有志之士... 现在想来,文章内容与题目有些不符,hehe
我们知道判断两个数互质充分必要条件是,两个数最大公约数=1, 这样,我们只需枚举i(1<=i<=n), 求gcd(i,m)即可,
辗转相除求gcd(i, m) 时间复杂度为logm+logi, 加上枚举时间,复杂度就为为 n*logm+logn!
若问题仅求一次m,近乎线性时间,是不错解决方案;但如果,如此取值m,比如在[1...n]中随即选取k个数,求每个
数在[1..n]中互质的个数,那么问题复杂度就变成O(k*n)了, 若n=50000, k=10000(即5个数中选取1个), 时间近乎数
十秒,这将不可忍受。
另法,快速求得[1..n]中与m不互素的个数res, 则n-res...
费费定理: 若整数i与m不互素,则m所有质因子中,至少一个也是i的质因子
步骤一:分解m求其质因子
方法,枚举[2..sqrt(m')]试除m';这里m'初始值m,每次枚举到一个质因子,便除去m'中所有此因子,
因此平均时间远小于sqrt(m), 但最坏情况下仍使sqrt(m), 可以做个优化,预处理[1..n]生成素数表(n=50000, 素数约5000),
筛选法求素数表时间O(3*n),然后直接拿生成的素数试除。
步骤二:求不互质个数
假设m分解后,质因子为p[pCnt], 那么[1...n]中包含这些质因子的数目为:
公式: 若pCnt=3,则
n/p[1]+n/p[2]+n/p[3]-n/(p[1]*p[2])-n/(p[1]*p[3])-n/(p[2]*p[3])+n/(p[1]*p[2]*p[3])
忘了这个叫什么来着,似乎是鸽巢定理的扩展吧。
其实pCnt值非常小,若n=50000, 则pCnt<7, 因为 2*3*5*7*11*13*17 >> 50000
这样,我们就可以简单深搜一下,计算上面公式的值,dfs时间 pCnt*2^pCnt (=384, n=50000时)
如此,总时间为O(k*t) t=sqrt(m)+pCnt*2^pCnt (t<600,n=50000时) 近乎于n无关,
因此,即使n=50000, k=10000, 计算复杂度也不超10^7,1s内, 实际上本机运行,不过几十ms.
至此,问题得到解决,从数十s到几十ms。
应该有更好的算法,期待有志之士... 现在想来,文章内容与题目有些不符,hehe
相关文章推荐
- 判断两个数是否互质
- 浅析Windows 2003的两种快速自动登录捷径
- 如何快速判断你的网段内谁的网卡处在混杂模式
- PHP取二进制文件头快速判断文件类型的实现代码
- 怎样快速判断一个数组中,和值(任意1个或几个的和) 是否等于某值:
- java判断字符串String是否为空问题浅析
- 线段交叉判断(快速排斥实验 + 跨立实验)
- 快速判断一个数能否被1、2、3、4、5、6、7、8、9、10、11、12、13、17、19、23等整除的规律总结
- 快速判断一个数能否被1、2、3、4、5、6、7、8、9、10、11、12、13、17、19、23等整除的规律总结
- 如何快速判断一个数是不是2幂数
- 快速判断测试前后的Codes是否是正确的
- 快速判断一个数是否是2的幂次方,若是,并判断出来是多少次方!
- python中快速判断一个对象是否是字符串
- 快速判断素数
- 快速开发之网络判断工具类
- 阅读中的T/F/NG的快速判断法
- 46 leetcode - 如何快速判断一个数是不是2的幂、3的幂、4的幂
- 用Socket快速判断数据库连接
- 快速判断一个数是否是2的幂次方
- 关于解决快速判断longlong型的整数是否为素数