文章目录
- 阶乘分解(素数因子)
- 探索版
- AC版:
- python_阶乘递归求解/尾递归形式/字典形式求解
阶乘分解(素数因子)
探索版
/*问题D:
题目描述
输入正整数n (2<n<100),把阶乘n! =l*2*3x...xn分解成素因子相乘的形式,输出各个素数(2、3、 5......)的指数。
例如825=3*5以*11应表示成(0、1、2、0、1),表示分别由0、1、2、0、1个2、3、
5、7、11。要求你的程序在输出时忽略比正整数n的最大 素因子 更大的素数,否则会导致末尾有无穷多个 0。
输入
输入正整数n (2<n<100)[多组测试数据]
输出
n!=(—个空格)a1(—个空格)a2(—个空格)a3...
[a1,a2,a3等数字为分解后素数(2、3、5......)的指数,输出时忽略大于最大素因子的素数的指数0。]
样例输入
5
53
样例输出
5!= 3 1 1
53!= 49 23 12 8 4 4 3 2 2 1 1 1 1 1 1 1
*/
int is_prime(int i)
{
if (i == 1 || i == 0)
{
return 0;
}
for (int j = 2; j*j < i+1; j++)
{
if (i % j == 0)
{
return 0;
}
}
return 1;
}
int main()
{
int n;
int cnt = 0;
int prime[2][100] = { 0 };/*n<=100;用{0}可以将二维数组里的元素都初始化为0;
prime[0][100]保存质数列表;
prime[1][100]保存计数情况,各个元素充当各个质数的计数器*/
/*填充质数列表*/
for (int i = 2, j = 0; i < 100; i++)
{
if (is_prime(i))
{
prime[0][j++] = i;
}
}
/*处理多组输入:*/
while (scanf("%d", &n) != EOF)
{
/*每组测试数据开始前初始化计数器.*/
for (int j = 0; j < 100;j++)
{
prime[1][j] = 0;
}
int bak = 0;/*back-up 备份.*/
/*阶乘的各个因子分别进行质数因子拆分,使得问题规模分摊在各相似的子问题上*/
for (int i = 2; i <= n;i++)
{/*eg.i = 100时:*/
bak = i;/*辅助变量很重要;处理阶乘因子i*/
for (int j = 0; bak >=2;)
{
if (bak % prime[0][j] == 0)/*bak不要写成i,在这gg了好几回*/
{
/*同一个质数的属性*/
bak = bak / prime[0][j];
prime[1][j]++;
}
else
{
j++;
}
}//for
}//for
/*打印*/
for (int i = 0; prime[0][i] <= n && prime[0][i] > 0 && i < 100;/*仅第一个条件还不够,无法处理99之类的大数;大于n的素数必定会出现在n!的因子中,它们比>=1(因为它们质数还不可以被分解,哪些非1(>1)的是某些合数因子被分解为对应质因子的结果.;i<100是为了保证不打印数组越界后的乱七八糟的数*/
i++)
{
printf("%d ", prime[1][i]);
}
printf("\n"); }
}
/*彩蛋*/
/*int s = 1; long long 是_int64 */
///*这种做法的弊端是有时long long 都难以装下(规模和大的时候)*/
//for (int i = 1; i <= n; i++)
//{
// s *= i;
//}*/
//for (int i = 2; s > 0;)
//{
// if (i > bak)
// {
// break;
// }
// if (s % i == 0 && is_prime(i) )
// {
// s /= i;
// cnt++;
// }
// else
// {
// if (is_prime(i))
// {
// printf("%d ", cnt);
// }
// cnt = 0;
// i++;
// }
//}//for
AC版:
int isprime(int n)
{
if(n == 1 || n == 0)
{
return 0;
}
else
{
for(int i = 2;i*i<n+1;i++)
{
if(n%i == 0)
{
return 0;
}
}
}
return 1;
}//dui
int main()
{
int prime[2][100] = {0};
int i = 0,j = 0 ;
for(i = 0;i<100;i++)
{
if(isprime(i))
{
prime[0][j++] = i;
}
}//dui
int n = 0;
while(scanf("%d",&n) != EOF)
{
for(i = 0;i<100;i++)
{
prime[1][i] = 0;
}//dui
for(int i = 2 ;i<=n;i++)
{
int bak = i;
for(int k = 0;bak>1;)
{
if(bak%prime[0][k]== 0)
{
bak = bak/prime[0][k];
prime[1][k] ++;
}
else
{
k++;
}
}//for
}//for
printf("%d!= ",n);
for(int i = 0;prime[0][i]<=n && prime[1][i] >0;i++)
{
printf("%d",prime[1][i]);
if(prime[1][i+1]>0)//格式错误的处理(最后的空格不要)
{
printf(" ");
}
}
printf("\n");
}//while
}
python_阶乘递归求解/尾递归形式/字典形式求解
python没有尾递归优化
比如,即使采用尾递归形式在计算1000!的时候会爆栈
RecursionError: maximum recursion depth exceeded in comparison
def factorial(n):
"""传统递归方式编写计算阶乘的函数
Parameters
----------
n : int
速度较慢,譬如(n=100)
Returns
-------
计算结果
"""
if n == 0:
return 1
return n * factorial(n - 1)
def fact_iter(num, product=1):
"""尾递归的形式实现阶乘
Parameters
----------
num : int
表示需要计算的阶乘的数
同时表征递归出口(运算次数)
product : int
累计计算结果,最终在递归出口返回
在本调用的执行过程中,后面的函数调用传入的参数累计了上一次调用的计算结果
Returns
-------
int
计算结果
"""
# 定义递归出口
if num == 1:
return product
# num * product是计算关键
# num-1是通往出口的关键
return fact_iter(num - 1, num * product)
def factorail(n):
return fact_iter(n, 1)
print(factorial(100))
factorial_d=[1]
def factorial_speed(n):
"""fast factorial
Parameters
----------
n : int
需要计算阶乘的整数
Returns
-------
int
calculate result
"""
for n in range(1,n+1):
factorial_d.append( n * factorial_d[n - 1])
return factorial_d[n]
if __name__=="__main__":
res=factorial(100)
print("res1:",res)
res=factorial_speed(50)
print("res2:",res)