文章目录
- 阶乘分解(素数因子)
 
- 探索版
 - 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++;
    //  }
    //}//forAC版:
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)                
                
