计算机算法设计与分析课本(王晓东著)课后算法实现题1-3 最多约数问题

问题描述: 正整数x的约数是能整除x的正整数。正整数x的约数个数记为div(x)。例如,1 2 5 10都是10的约数,且div(10)=4。设a和b是2个正整数,a<=b,找出a和b之间约数个数最多的数x。
算法设计: 对于给定的2个正整数a<=b,计算a和b之间约数个数最多的数。
数据的输入与输出: 输入文件示例 输出文件示例
1 36 9
问题分析: 可以用暴力求解的方法直接求出数的约数的个数,时间复杂度为O(n),随着数的增大时间复杂度也将增大,不合适,这里可以使用约数个数定理,n分解质因数 n=p1^a1 * p2^a2 * p3^a3 pk^ak则n的约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1),在求解质因数的过程中数字不断减小,时间复杂度为O(logN)

/*****************************************************************
source:算法课本实现题1-3
mean of the title:给定两个正整数,计算两个数之间约数个数最多的数
并输出此数的约数个数
版本2.0:约数个数定理,n分解质因数 n=p1^a1*p2^a2*p3^a3*…*pk^ak
则,n的约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1)
*****************************************************************/

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;

int prime_num[10000];//存储质因子的个数 

int isprime(int n){//判断n是否是质因数
	bool flag = true;
	for (int i = 2; i <= sqrt(n); i++){
		if (n%i == 0){
			flag = false;
			break;
		}
	}
	return flag;
}

int solve(int n){//求n的约数个数 
	memset(prime_num, 0, sizeof(prime_num));
	int count = 1;
	int num = n;
	if (num == 1)
		return 1;
	if (isprime(num))
		return 2;
	for (int i = 2; i <= sqrt(num); i++){//分解质因子 
		if (!(n%i)){
			prime_num[i]++;
			n /= i;
			i--;//还原i,质因子可能重复 
		}
	}
	for (int i = 2; i <= num; i++){
		if (prime_num[i]){
			//cout<<"prime_num["<<i<<"]="<<prime_num[i]<<endl;
			count *= (prime_num[i] + 1);
		}
	}
	return count;
}

int main(){
	int a, b;
	int max = 0;
	cout << "Enter two integers a and b:";
	cin >> a >> b;

	for (int i = a; i <= b; i++){
		if (solve(i)>max){
			max = solve(i);
		}
	}
	cout << "The largest number of divisor is " << max << endl;
	return 0;
}

暴力求解的代码

#include<iostream>
#include<cmath>
using namespace std;
int main(){
	int a,b;
	int number,max=0;
	cout<<"Enter two integers a and b:";
	cin>>a>>b;
	
	for(int i=a;i<=b;i++){
		number=0;
		for(int j=1;j<=sqrt(i);j++){
			if(!(i%j)){
				if(j!=(i/j))
					number+=2;
				else
					number+=1;
			}
				
		}
		if(number>max)
			max=number;
	}
	
	cout<<"The largest number of divisor is "<<max<<endl;
	return 0;
}
//时间复杂度为O((b-a)*sqrt(i)),随着b的增大,i增大,时间复杂度增长 

附加
对于约数个数定理证明的一些个人思路
假设n=2^ n1 3^n3,那么n等于n1个2乘以n2个3,然后从n1个2中取一个2,那么从n2个3中就可以取(n2+1)个3和2相乘,每乘一次原数就会多出两个约数,如果从n1个2中取两个2,那么从n2个3中还是可以取(n2+1)个3和2个2相乘,那么原数就又会多出2(n2+1)个约数,那么扩展到n1个2,因为取0个2的时候36从n1个2中一共可以取(n1+1)个2(取0个2时是1和原数相乘),那么原数将一共有2*(n1+1)*(n2+1),因为有重复,所以最后要除以2

猜你喜欢

转载自blog.csdn.net/Dear_Jia/article/details/85039726