快速階乘運算

在前一篇blog中提到了logn複雜度求出C(n,r),利用此結果在(logn)^2複雜度下計算n!

oh, fuck!!! 校園招聘微軟的三面面試官出了這道bug題。。。

分析:利用下面的公式可以降低複雜度

由於C(n, n/2)需要logn複雜度計算出來,加上n!所需的logn,所以總體複雜度爲(logn)^2,代碼如下:

#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

#define MAXSIZE 100
unsigned long answer[MAXSIZE];

unsigned long long int power(unsigned long base, unsigned long exp)
{
	unsigned long long int result = 1;
	while (exp)
	{
		if (exp & 0x01)
			result *= base;
		base *= base;
		exp >>= 1;
	}

	return result;
}

unsigned long cn2(unsigned long n)
{
	unsigned long x = (1 << n) + 1;
	unsigned long mask = (1 << n) - 1;

	return (power(x, n) >> ((n >> 1) * n)) & mask;
}

unsigned long factorial(unsigned long n)
{
	unsigned long temp;

	if (n == 1)
		return 1;
	else if (n & 0x01 == 1)
		return n * factorial(n - 1);
	else
	{
		temp = factorial(n >> 1);
		return cn2(n) * temp * temp;
	}
}

void main()
{
	int number = 4;
	unsigned long result = factorial(number);
	cout << "result = " << result << endl;
}

更快速的階乘運算,只需要log(n)複雜度

我們可以看到cn2(n)需要logn的複雜度計算出來,可以提前計算出來存放在數組中,由於每次計算C(n,n/2), C(n/2, n/4), ... 這樣在求解power的過程中,就可以計算出來~

#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

#define MAXSIZE 100
unsigned long mask;
unsigned cnrs[MAXSIZE];
int number;
int p_size;

unsigned long power(unsigned long n, unsigned long m)
{
	unsigned long temp;

	if (m == 1)
		temp = n;
	else if (m & 0x01 != 0)
		temp = n * power(n, m - 1);
	else
	{
		temp = power(n, m >> 1);
		temp *= temp;
		cnrs[number++] = (temp >> ((m >> 1) * p_size)) & mask;
	}

	return temp;
}

unsigned factor(unsigned long n)
{
	unsigned long temp;

	if (n == 1)
		return 1;
	else if (n & 0x01 == 1)
		return n * factor(n - 1);
	else
	{
		temp = factor(n >> 1);
		return cnrs[number++] * temp * temp;
	}
}

unsigned long factorial(unsigned long n)
{
	unsigned long x = (1 << n) + 1;

	number = 0;
	mask = (1 << n) - 1;
	p_size = n;
	power(x, n);
	number = 0;

	return factor(n); 
}

void main()
{
	int number = 6;
	unsigned long result = factorial(number);
	cout << "result = " << result << endl;
	copy(cnrs, cnrs + 10, ostream_iterator<int>(cout, " "));
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章