快速阶乘运算

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




评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值