第k小因子

题目:给定一个数 n, 1<= n<=10^15,求第k小因子。假设10^8次执行时间为1s。


这道题我相信大家都能够想到O(n)的解决方法,但是考虑到时间复杂度,如果一个数为10^15次方,这将是一个很大的计算时间,因此O(n)不可取。


接下来提供一个 O(n^(1/2))的方法,其实也很简单,就是只遍历 sqrt(n)次,因为因子数是一一对应的(比如24,我们求出了因子3,那么因子8也就能够求出来)。如此下来,我们的计算时间可以控制在1s以内。


思路:

假设 n=24;

用两个数组a、b分别保存小因子数(如 1,2,3,4)和大因子数(24,12,8,6),大因子数可以通过 【n/小因子数】得到。

得出第k小因子与a、b数组元素个数之间的关系,求出最终结果。


注意:

1. 所有的 数用 unsigned long long 数据类型,以防越界;

2. 对于25这种(存在 5*5的情况),不要重复记录因子个数。


以下是源代码:


#include<iostream>
#include<cmath> 
using namespace std;
unsigned long long theKFactor(unsigned long long n, int k)  
{
	unsigned long long a[1000],b[1000],j(0),t(0),count(0); 
	for (long long int i = 1; i <= sqrt(n); i++) {
		if (n % i == 0) {
			unsigned long long large = n/i;  // i 和 n/i 
			a[j++] = i;  // 数组 a 记录小因子数 
			if (i != large) b[t++] = large;  // 防止重复的因子,数组 b 记录大因子数 
			count++;
			if (k == count) break;  // 提前找到,直接退出 
		}	
	}
	// 此时,j 为数组 a 中因子个数,t为数组 b 中因子个数 
	if (k <= 0 || k > j + t) return 0;  // 不合法的 K, 返回 0 
	if (k <= j) return a[k-1];  // 小于一半 
	else return b[t-(k-j)];   // 大于一半 
}

int main()
{
	unsigned long long max = theKFactor(1000000000000000,256);  // 1000000000000000,由此可知其有 256 个因子 
	cout<<max<<endl;
	max = theKFactor(1000000000000000,128);  // 31250000
	cout<<max<<endl;
	max = theKFactor(25,3);   // 25,因子 5只能算 1 次 
	cout<<max<<endl;
	max = theKFactor(15,3);  // 5
	cout<<max<<endl;
	max = theKFactor(24,9);  // 0,不合法的k 
	cout<<max<<endl;
	return 0;
}

计算结果:


由此发现,时间复杂度大大降低。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值