在前一篇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, " "));
}