問題描述
列印所有不超過n(取n<256)的其平方具有對稱性質的數(也稱回文數)。
問題分析
對于要判定的數n計算出其平方後(存于a),按照“回文數”的定義要将最高位與最低位、次高位與次低位……進行比較,若彼此相等則為回文數。此算法需要知道平方數的位數,再一一将每一位分解、比較,此方法對于位數已知且位數不是太多的數來說比較适用。
此問題可借助數組來解決。将平方後的(a的)每一位進行分解,按從低位到高位的順序依次暫存到數組中,再将數組中的元素按照下标從大到小的順序重新将其組合成一個數衆(如n=15,則a=225且k=522),若k等于n×n則可判定n為回文數。
算法設計
從低位到高位将某一整數拆分。對于一個整數(設變量名為a)無論其位數多少,若欲将最低位拆分,隻需對10進行求模運算a%10,拆分次低位首先要想辦法将原來的次低位作為最低位來處理,用原數對10求商可得到由除最低位之外的數形成的新數,且新數的最低位是原數的次低位,根據拆分最低位的方法将次低位求出a/10、a%10,對于其他位上的數算法相同。
利用這個方法要解決的一個問題就是,什麼情況下才算把所有數都拆分完?當拆分到隻剩原數最高位時(即新數為個位數時),再對10求商的話,得到的結果肯定為0,可以通過這個條件判斷是否拆分完畢。根據題意,應将每次拆分出來的資料存儲到數組中,原數的最低位存到下标為0的位置,次低位存到下标為1的位置……依次類推。
程式段如下:
for (i=0; a!=0; i++) { m[i] = a % 10; a /= 10; }
将數組中元素重新組合成一新數。拆分時變量a的最高位仍然存儲在數組中下标最大的位置,根據“回文數”定義,新數中資料的順序與a中資料的順序相反,是以我們按照下标從大到小的順序分别取出數組中的元素組成新數k,由幾個數字組成一個新數時隻需用每一個數字乘以所在位置對應的權值然後相加即可,在程式設計過程中應該有一個變量t來存儲每一位對應的權值,個位權值為1,十位權值為10,百位權值為100……,是以可以利用循環,每循環一次t的值就擴大10倍。對應程式段如下:
for( ; i>0; i--) { k += m[i-l] * t; t *= 10; }
下面是完整的代碼:
#include int main() { int m[16], n, i, t, count=0; long unsigned a, k; printf("No. number it's square(palindrome)n"); for( n=1; n<256; n++ ) { k=0; t=1; a=n*n; for( i=0; a!=0; i++ ) { m[i] = a % 10; a /= 10; } for(; i>0; i--) { k += m[i-1] * t; t *= 10; } if(k == n*n) printf("%2d%10d%10dn", ++count, n, n*n); } return 0; }
運作結果:
No. number it's square(palindrome) 1 1 1 2 2 4 3 3 9 4 11 121 5 22 484 6 26 676 7 101 10201 8 111 12321 9 121 14641 10 202 40804 11 212 44944