对阶乘的另类运算方式
作者:互联网
在开始之前,我们先列出每一种运算所需的时间复杂度
我们推出对阶乘的含义:
n!=1 * 2 * 3 * 4 *...n
然后经过如下变形:
1 *2 * 3 * 4 * 5..n=2 * 4 * 6 * 8 * 10 *...2n/2^n,
即:
(2n)!/[(1 * 3 * 5...(2n-1]* 2^n )=n!
令2n=t,有:
t!= (t/2)! * (1 * 3 * 5...t-1 * t)*2^(t/2)
over
当然,以上代码可以经过迭代,但最后的复杂度可能高于原阶乘
代码实现:
c语言:
int test(int n) {
int i,d=1;
switch (n){
case 1:
return 1;
case 2:
return 2;
case 3:
return 6;
}
for (i = 1; i < n - 1; i+=2) {
d *= i;
}
if (n & 1) {
return d;
}
else {
return test(n / 2) * d* 2<<(n/2);
}
}
而对于“是否有必要”,我做了个可供测试的子函数(太快了,测不到)
点击查看代码
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#include <string.h>
int main() {
long long i = NULL, j = NULL, k = NULL;
long long int n = 500, d = 1;
double add_i, add_j, add_k, end_i, end_j, end_k;
add_i = clock();
i=test_1(n);
end_i = clock();
add_j = clock();
j = test_2(n);
end_j = clock();
add_k=clock();
while (--n)
d *= n;
end_k=clock();
k =d ;
printf(" i %21d,%f j %21d,%f k %21d,%f", i,add_i-end_i,j, add_j - end_j,k, add_k - end_k);
return 0;
}
int test_1(int n) {
int i, d = 1;
switch (n) {
case 1:
return 1;
case 2:
return 2;
case 3:
return 6;
}
for (i = 1; i < n - 1; i += 2) {
d *= i;
}
if (n & 1) {
return d;
}
else {
return test_1(n / 2) * d * 2 << (n / 2);
}
}
int test_2(int n) {
int i, d = 1, m = n / 2, t=1;
switch (n) {
case 1:
return 1;
case 2:
return 2;
case 3:
return 6;
}
while (--m)t *= m;
for (i = 1; i < n - 1; i += 2) {
d *= i;
}
return d * 2 << (n / 2) * t;
}
发现这样的阶乘好像也没有多快..和我之前想的不一样
标签:end,运算,int,另类,test,add,阶乘,return,include 来源: https://www.cnblogs.com/miaomiaomiaomiao/p/15707397.html