1. 程式人生 > >計算機演算法設計與分析課本(王曉東著)課後演算法實現題1-3 最多約數問題

計算機演算法設計與分析課本(王曉東著)課後演算法實現題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