完美數

文章推薦指數: 80 %
投票人數:10人

完美數. December 2, 2021. 如果數字n,真因數(Proper factor)的總和等於n,稱為完美數(Perfect Number),例如以下幾個數都是完美數:. 6 = 1 + 2 + 3. OPENHOME.CC 常見程式演算 |老掉牙 河內塔 費式數列 巴斯卡三角形 三色旗 老鼠走迷宮 騎士走棋盤 八皇后 八銀幣 康威生命遊戲 字串比對 背包問題 雙色、三色河內塔 得分排行 |「數」 最大訪客數 Eratosthenes篩選求質數 完美數 阿姆斯壯數 大數運算 指定位數的圓周率 |隨機 蒙地卡羅法求PI 洗牌 Craps賭博遊戲 約瑟夫問題 |組構 排列 格雷碼 子集 k組合 因數分解 加法因子 |排序 選擇、插入、氣泡排序 Heap排序-改良的選擇排序 Shell排序-改良的插入排序 Shaker排序-改良的氣泡排序 快速排序(一) 快速排序(二) 合併排序 基數排序 |搜尋 線性搜尋 二分搜尋 插補搜尋 費氏搜尋 |矩陣 稀疏矩陣 多維矩陣降維 上/下三角、對稱矩陣 奇數魔方陣 4N魔方陣 2(2N+1)魔方陣 |運算 中序式轉後序式 後序式運算 Quine GitHub Twitter Facebook LinkedIn Designs Tags BuiltwithbyHugo HOME> 常見程式演算> 「數」> 完美數 解法思路 程式實作: perfectnumber primenumber factoring C Java Python Scala Ruby JavaScript Haskell 完美數 December2,2021 如果數字n,真因數(Properfactor)的總和等於n,稱為完美數(PerfectNumber),例如以下幾個數都是完美數: 6=1+2+3 28=1+2+4+7+14 496=1+2+4+8+16+31+62+124+248 第一眼看到時,會想到使用迴圈求出全部真因數,再進一步求因數和,不過若n值很大,會花費許多時間在迴圈測試上,十分沒有效率。

解法思路 如何求小於n的全部完美數?並將程式寫的有效率?基本上有三個步驟: 建立質數表。

利用質數表求指定數的因式分解。

利用因式分解求全部真因數和,並檢查是否為完美數。

步驟1與2在〈Eratosthenes篩選求質數〉與〈因數分解〉已經討論過,問題在步驟3,如何求真因數和?首先要知道將全部真因數和加上該數本身,會等於該數的兩倍,例如: 2*28=1+2+4+7+14+28 等式後面可以化為: 2*28=(2⁰+2¹+2²)*(7⁰+7¹) 只要求出因式分解,就可以利用迴圈求得等式後面的值,將該值除以2就是真因數和;等式後面第一眼看時可能想到使用等比級數公式來解,不過會使用到次方運算,可以在迴圈走訪因式分解陣列時,同時計算出等式後面的值。

程式實作: C Java Python Scala Ruby JavaScript Haskell #include #include #defineP10000 #defineN5000 voidcreate(int*);//建立質數表 voidfilter(int*,int); voidfactor(int,int*,int*);//因數分解 intisPerfect(int,int*);//判斷完美數 intmain(void){ intprimes[N+1]={0}; create(primes); inti; for(i=2;i<=P;i++)if(isPerfect(i,primes)){ printf("PerfectNumber%5d\n",i); } return0; } voidcreate(int*primes){ primes[2]=primes[3]=primes[5]=1; inti; for(i=1;6*i+5<=N;i++){ primes[6*i+1]=primes[6*i+5]=1; } if(6*i+1<=N){primes[6*i+1]=1;} intn; for(n=0;(6*n+5)*(6*n+5)<=N;n++){ filter(primes,6*n+1); filter(primes,6*n+5); } if((6*n+1)*(6*n+1)<=N){filter(primes,6*n+1);} } voidfilter(int*primes,inti){ if(primes[i]){ intj; for(j=2;j*i<=N;j++){ primes[j*i]=0; } } } voidfactor(intnum,int*factors,int*primes){ inti,j; for(i=2,j=0;i*i<=num;)if(primes[i]&&num%i==0){ factors[j++]=i; num/=i; }else{i++;} factors[j]=num; } intisPerfect(intnum,int*primes){ intfactors[N/2+1]={0}; factor(num,factors,primes); ints=1; inti=0; while(factors[i]!=0){ intr=1; intq=1; do{ r*=factors[i]; q+=r; i++; }while(factors[i-1]==factors[i]); s*=q; } returns/2==num; } //使用Eratosthenes篩選求質數中的Prime //使用因數分解中的Factor importjava.util.*; publicclassPerfect{ publicstaticListperfectLe(intn){ Listprimes=Prime.create(n/2); Listperfects=newArrayList<>(); for(inti=2;i<=n;i++)if(isPerfect(i,primes)){ perfects.add(i); } returnperfects; } publicstaticbooleanisPerfect(intnum,Listprimes){ Listfactors=Factor.factor(num,primes); factors.add(0); ints=1; inti=0; while(factors.get(i)!=0){ intr=1; intq=1; do{ r*=factors.get(i); q+=r; i++; }while(factors.get(i-1).equals(factors.get(i))); s*=q; } returns/2==num; } publicstaticvoidmain(String[]args){ for(Integern:perfectLe(100000)){ System.out.printf("Perfectnumber%5d%n",n); } } } fromfunctoolsimportreduce#未使用質數表 defperfectLe(number): return[iforiinrange(1,number)if2*i==reduce(\ lambdasum,k:sum+kifi%k==0elsesum,range(1,i+1))] print(perfectLe(10000)) defperfectLe(number:Int)={//未使用質數表 for( iif(i%k==0)sum+kelsesum} )yieldi } perfectLe(10000)foreach(p=>print(p+"")) classRange defcomprehend(&block) returnselfifblock.nil? self.collect(&block).compact end end defperfectLe(number) (1..number-1).comprehend{|i| iif2*i==(1..i).reduce{|sum,k|i%k==0?sum+k:sum} } end pperfectLe(10000) functionrange(start,end){ varr=[]; varn=start; for(vari=0;nifi`mod`k==0thens+kelses)[1..i])] main=print$perfectLe10000



請為這篇文章評分?