天天看點

c_階乘分解素數因子(制作字典解決)/python_階乘遞歸求解/尾遞歸形式/字典/循環加速

文章目錄

  • ​​階乘分解(素數因子)​​
  • ​​探索版​​
  • ​​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
*/
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>
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版:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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_階乘遞歸求解/尾遞歸形式/字典形式求解

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)