*思考題將1、2、3、4、5、6、7、8、9九個數字分成以下三種帶分數形式之一,每個數字只能用一次,使得該分數剛好等於一個整數。
N=X+XXXX/XXXX,N=X+XXXXX/XXX,N=XX+XXXX/XXX
例如:100=3+69258/714=81+5643/297(原書上寫的是81+5648/297,錯誤)求所有滿足條件的表示形式。(參考答案:某些自然數沒有這種表示形式,如:1、2、3、4、15、18等。此外整數100有11種滿足條件的表示形式;89的表示形式最多,共有36種;三種形式中,最大可表示的整數為794。)
*問題分析與演算法設計基本思路是先構造數字不重複的分子,再從剩下的數字中構造一個加數,最後由構造分子和加數剩下的數字構造數字不重複的分母,然後判斷和是不是整數,如果是,則列印出來。每一種形式的運算量都比較大,所以把他們各自寫成一個完整的程式。3個程式之間的修改主要在:數位,判斷條件,迴圈結束條件。
#include <stdio.h>#include <stdbool.h>bool CheckNum(int number);bool CheckDiv(int number);int main(){int i,j,k,l,m,n,num,den,inte,sum,count=1;int a[2][9]={1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,0,0};int b[4];for(n=1;n<17;n++)//N=X+XXXX/XXXX,N的最大值為9+8765/1234<17{for(num=1234;num<=9876;num++){if(!CheckNum(num)) continue;//檢查分子的正確性,無重複數字且不含0for(j=1,i=0;i<4;i++){k=num/j%10;//給分子的每一位的標誌位置1,從個位開始a[1][k-1]=1;j=10*j;}//這時已經用掉了4個數for(i=0;i<9;i++){if(a[1][i]==0){inte=a[0][i];//從剩下的5個數中取一個數做為加數,並把它的標誌位置1a[1][i]=1;for(k=0,j=0;k<9;k++)//再把剩下的4個數字存到數組b中{if(a[1][k]==0){b[j]=a[0][k];j++;}}for(j=0;j<4;j++)//用數組b中的4個數字來組成除數{for(k=0;k<4;k++){for(l=0;l<4;l++){for(m=0;m<4;m++){den=1000*b[j]+100*b[k]+10*b[l]+b[m];if(!CheckDiv(den)) continue;//有重複就重新構造除數sum=inte+num/den;if(num%den==0&&n==sum){ printf("[%d] %d=%d+%d/%d\n",count++,sum,inte,num,den);}}}}}a[1][i]=0;//選下一個數作為加數,把這個加數的標誌位置0,留用於構造除數}}for(i=0;i<9;i++)//重新給所有數位標誌位置0,準備開始下一輪迴圈{a[1][i]=0;}}}return 0;}bool CheckNum(int number)//檢查被除數的正確性{int temp,i,j,k,a[4];for(k=1,i=0;i<4;i++){temp=number/k%10;if (temp==0){return false;//如果某一位出現0,則找下一個數}k=10*k;a[i]=temp;}for(i=0;i<4;i++)//檢查是否有數字重複{for(j=i+1;j<4;j++){if(a[i]==a[j]) return false;//有重複,返回false}}return true;//未出現0且數字不重複,返回true}bool CheckDiv(int number)//檢查除數的正確性{int temp,i,j,k,a[4];for(k=1,i=0;i<4;i++){temp=number/k%10;k=10*k;a[i]=temp;}for(i=0;i<4;i++)//檢查是否有數字重複{for(j=i+1;j<4;j++){if(a[i]==a[j]) return false;//有重複,返回false}}return true;//未出現0且數字不重複,返回true}