1. 程式人生 > >c++ 正整數拆分成素因子的乘積

c++ 正整數拆分成素因子的乘積

#include<string>
//設計演算法,將某個大於1的數分成素因子的乘積 6=2*3  7=7 8=2*2*2
//1.判斷當前數是不是素數,是直接返回
//2.否則,迴圈直到第一個它能整除的素數,當前數變為除以素數後的商,繼續大迴圈。
//判斷一個數是不是素數
#include <math.h>
bool isPrime(int x){
	if (x <= 1)
		return false;
	if (x == 2)
		return true;
	if (x % 2 == 0)
		return false;
	int tmax = (int)sqrt(x) + 1; //sqrt(9)返回的是浮點數,有可能是2.9999或3.00001等,確保正確性,多比較一次
	int i = 3;
	while (i < tmax){
		if (x%i == 0)
			return false;
		i+=2;
	}
	return true;
}

string primeMulti(int x){
	string s = "";
	s+= to_string(x)+"=";
	while (x != 1){
		if (isPrime(x)){
			s =s+ to_string(x);
			return s;
		}
		if (x % 2 == 0){
			s += "2*";
			x /= 2;
		}
		for (int i = 3; i <= x; i += 2){
			if (isPrime(i) && x%i == 0){
				s += to_string(i) + "*";
				x /= i;
				break;
			}
		}
	}
	if (x == 1)  //若最終x為1,需去掉尾上多餘的乘號
		s = s.substr(0,s.size()-1);
	return s;
}

改進:先把小於該數的素數求出來,儲存在vector中,可以減少素數的重複判斷

#include <iostream>
#include <string>
#include <vector>
#include <math.h>

using namespace std;
bool isPrime(long n){
	if (n <= 1)
		return false;
	else if (n == 2)
		return true;
	else if (n % 2 == 0)
		return false;
	else{
		int maxsqr = (long)sqrt(n) + 1;
		for (long i = 3; i<maxsqr; i = i + 2){
			if (n%i == 0)
				return false;
		}
	}
	return true;
}
void prime(long n, vector<long>& vec){
	if (n <= 1)
		return;
	for (long i = 2; i <= n; ++i){
		if (isPrime(i))
			vec.push_back(i);
	}
	return;
}

int main(){
	vector<long> v = {};
	long n;
	cin >> n;
	prime(n, v);
	while (n != 1){
		long i = 0;
		while (v[i] <= n){
			if (n%v[i] == 0){
				cout << v[i] << " ";
				n = n / v[i];
				break;
			}
			++i;
		}
	}
    cout << endl;
	return 0;
}

發現一個更簡單的,不用判斷是不是素數,直接除以比n小的數即可。
void primeFactor(long n){
    if(n<=1)
        return;
    while(n!=1){
        for(int i=2;i<=n;++i){
            if(n%i==0){
                cout << i << " ";
                n=n/i;
                break;
            }
        }
    }
}


加一個其它習題:

//設計演算法,求二項式c(n,k)的係數
//c(n,k)=c(n,k-1)+c(n-1,k-1)
int er(int n,int k){
	if (k == 0 || k==n)
		return 1;
	if (k > n / 2)
		k = n - k;
	return er(n- 1, k) + er(n - 1, k - 1);
}

再加一個漢諾塔問題,都是用遞迴實現的。遞迴可以讓程式碼更簡潔,甚至解決一些迴圈不能解決或解決起來超級複雜的問題

void move(int n,char from, char to){
	cout <<n<<":"<< from << "->" << to << endl;
}
//實現漢諾塔盤子移動
//關鍵點:只有一個盤子,直接把它從from移動到to,否則,先移動n-1個盤子,以to為臨時柱子
//移動到tmp;再移動第n個盤子到to;最後將那n-1個盤子從tmp以from為臨時柱子移動到to
void hanuota(int n, char from, char tmp, char to){
	if (n == 1)
		move(n,from, to);
	else{
		hanuota(n - 1, from, to, tmp);
		move(n,from, to);
		hanuota(n - 1, tmp, from, to);
	}
}

執行hanuota(3,'A','B','C');得到的輸出: