首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言問答

C語言判斷完數(完全數):標準算法與優化版完整代碼

     編輯:C 語言問答

定義回顧

完數(完全數):等於其所有真因子(不含自身)之和的自然數。
例子:6 = 1+2+3,28 = 1+2+4+7+14,496,8128...

標準實現(O(√n) 優化)


#include 
#include 

int is_perfect(int n) {
    if (n <= 1) return 0;
    int sum = 1;  // 1 是所有 n>1 的因子
    int limit = (int)sqrt(n);

    for (int i = 2; i <= limit; i++) {
        if (n % i == 0) {
            sum += i;
            int paired = n / i;
            if (paired != i) sum += paired;  // 避免平方數重複加
        }
    }
    return sum == n;
}

int main() {
    int n;
    printf("輸入正整數: ");
    scanf("%d", &n);
    if (is_perfect(n))
        printf("%d 是完數\n", n);
    else
        printf("%d 不是完數\n", n);
    return 0;
}

複雜度對比

已知完數查表法(工程最快)


int is_perfect_fast(int n) {
    // 32位有符號範圍內僅有 4 個完數
    static const int perfect[] = {6, 28, 496, 8128};
    for (int i = 0; i < 4; i++)
        if (perfect[i] == n) return 1;
    return 0;
}

常見錯誤避坑

  1. for(i=1; i 包含 n 自身 → 和會偏大
  2. 忘記處理 i == n/i(完全平方數)導致因子重複相加
  3. sum 用 int 可能溢出(n>46340 時 i*i 溢出),建議 long long
  4. 輸入 1 判定為完數 → 1 無真因子,和為 0,非完數

擴展:尋找範圍內所有完數


void find_perfect_range(int limit) {
    for (int n = 2; n <= limit; n++) {
        if (is_perfect(n))
            printf("%d ", n);
    }
    printf("\n");
}
// 10000 以內輸出:6 28 496 8128

數學冷知識

  • 所有已知完數均為偶數,奇完數是否存在是未解懸案
  • 完數與梅森素數一一對應:2^p-1 為素數 → 2^(p-1)*(2^p-1) 為完數
  • 第 51 個完數(2018 發現)有超過 4900 萬位十進制數字
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方法時間複雜度適用範圍
暴力 1~n-1O(n)n < 10^5 可接受
√n 優化O(√n)n < 10^12 秒級
梅森素數公式O(1) 查表已知 51 個完數全為偶數,形式 2^(p-1)*(2^p-1)