例15 除法算式 問題描述 輸入正整數n(2≤n≤68),按從小到大輸出所有形如abcde/fghi=n的表達式。其中a~i為1~9的一個排列。 輸入格式 每行為一個正整數n (n <= 1500),輸入n=0結束。 輸出格式 輸出滿足條件的所有形如abcde/fghi=n的表達式,每個表達式占一行 ...
例15 除法算式
問題描述
輸入正整數n(2≤n≤68),按從小到大輸出所有形如abcde/fghi=n的表達式。其中a~i為1~9的一個排列。
輸入格式
每行為一個正整數n (n <= 1500),輸入n=0結束。
輸出格式
輸出滿足條件的所有形如abcde/fghi=n的表達式,每個表達式占一行,具體格式參見輸出樣例。
輸入樣例
4
20
62
0
輸出樣例
15768/3942=4
17568/4392=4
23184/5796=4
31824/7956=4
No Solution!
79546/1283=62
94736/1528=62
(1)編程思路。
本例需要先確定好窮舉的思路。雖然題目說a~i為1~9的一個排列,但窮舉1~9的所有排列顯然沒有必要。
可以窮舉除數fghi,這是一個4位數,最小可為1234,最大可為9876,然後按fghi*n計算出abcde,最後判斷這9個數字是否不相同。
為判斷9個數字是否相同,可以定義一個數組flag[10],其中flag[i]的值表示數字i在算式中出現的次數,顯然flag[1]~flag[9]的值全為1才滿足要求。
另外,在窮舉時進行適當優化。若計算出abcde小於12345,顯然除數fghi太小,直接增大除數進行下次窮舉;若計算出abcde大於98765,顯然除數fghi太大,不再可能找到解,直接退出窮舉迴圈。
(2)源程式。
#include <stdio.h>
int main()
{
int n,x,y,i,flag[10],t;
while (scanf("%d",&n) && n!=0)
{
t=0;
for (y=1234;y<=9876;y++)
{
x=y*n;
if (x<12345) continue;
if (x>98765) break;
for (i=0;i<10;i++)
flag[i]=0;
flag[x/10000]++; flag[x%10000/1000]++;
flag[x%1000/100]++; flag[x%100/10]++;
flag[x%10]++;
flag[y/1000]++; flag[y%1000/100]++;
flag[y%100/10]++; flag[y%10]++;
for (i=1;i<10;i++)
if (flag[i]!=1) break;
if (i==10)
{
printf("%d/%d=%d\n",x,y,n);
t++;
}
}
if (t==0) printf("No Solution!\n");
}
return 0;
}
習題15
15-1 完美立方
問題描述
a3 +b3 + c3 = d3為完美立方等式。例如13 + 63 + 83 =93。編寫一個程式,輸出100以內的所有四元組(a, b, c, d),使得a3 +b3 + c3 = d3,其中1≤a< b< c< d≤100。
輸入格式
無輸入
輸出格式
100以內所有滿足a3 +b3 + c3 = d3的四元組(a, b, c, d),每行輸出5組。
輸入樣例
無輸入
輸出樣例
( 3, 4, 5, 6) ( 1, 6, 8, 9) ( 6, 8, 10, 12) ( 2, 12, 16, 18) ( 9, 12, 15, 18)
( 3, 10, 18, 19) ( 7, 14, 17, 20) ( 12, 16, 20, 24) ( 4, 17, 22, 25) ( 3, 18, 24, 27)
……
(1)編程思路。
因為要求100以內所有滿足a3 +b3 + c3 = d3的四元組(a, b, c, d),因此先定義一個數組int cube[101];,且cube[i]的值賦i3,以便於後面直接引用。
從d出發進行窮舉,則窮舉範圍為
6≤d≤100
1≤a≤d-3
a+1≤b≤d-2
b+1≤c≤d-1
(2)源程式。
#include <stdio.h>
int main()
{
int i, a, b, c, d,cnt=0;
int cube[101];
for (i=1 ; i<=100; i++)
cube[i]=i*i*i;
for (d=6 ; d<=100; d++)
for (a=1; a<d-2; a++ )
{
if (cube[d] <cube[a]+cube[a+1]+cube[a+2]) break; // 沒必要繼續搜索b 和c
for (b=a+1 ; b<d-1; b++)
{
if (cube[d] <cube[a]+cube[b]+cube[b+1]) break; // 沒必要繼續搜索c
for (c=b+1; c<d; c++)
if (cube[d]==cube[a]+cube[b]+cube[c])
{
cnt++;
printf("(%3d,%3d,%3d,%3d) ",a,b,c,d);
if (cnt%5==0) printf("\n");
}
}
}
return 0;
}
15-2 分數拆分
問題描述
輸入正整數k,找到所有的正整數x≥y,使得1/k=1/x+1/y。
輸入格式
輸入包含多組測試數據,每組為一行,一個正整數k。
輸出格式
對每組數據先輸出解的個數,然後輸出全部的解,沒個解占一行。具體格式參見輸出樣例。
輸入樣例
2
12
輸出樣例
2
1/2=1/6+1/3
1/2=1/4+1/4
8
1/12=1/156+1/13
1/12=1/84+1/14
1/12=1/60+1/15
1/12=1/48+1/16
1/12=1/36+1/18
1/12=1/30+1/20
1/12=1/28+1/21
1/12=1/24+1/24
(1)編程思路。
乍一看窮舉的範圍好像無法確定,但由於x≥y, 有1/x≤1/y,
因此由1/k=1/x+1/y 可知 1/y =1/k-1/x≥1/k-1/y, 故 2/y≥1/k 即y≤2k。當然y≥k+1。這樣只要在k+1~2k範圍之內窮舉y,然後根據y嘗試計算出x即可。
(2)源程式1。
#include <stdio.h>
int main()
{
int k;
while (scanf("%d",&k)!=EOF)
{
int x,y,cnt=0;
for (y=k+1;y<=2*k;y++)
{
if(k*y%(y-k)==0)
{
cnt++;
}
}
printf("%d\n",cnt);
for (y=k+1;y<=2*k;y++)
{
if(k*y%(y-k)==0)
{
x=k*y/(y-k);
printf("1/%d=1/%d+1/%d\n",k,x,y);
}
}
}
return 0;
}
(3)源程式2。
在源程式1中,窮舉的迴圈進行了兩次,一次用迴圈求出解的個數,另一次用迴圈輸出各個解的情況。顯然,可以在用迴圈求解的個數時用數組將求得的解的情況保存下來,這樣就不用再次迴圈求解,直接輸出用數組保存的解的情況即可。
#include <stdio.h>
int main()
{
int k;
while (scanf("%d",&k)!=EOF)
{
int cnt=0;
int t;
int x[2*k],y[2*k];
for (t=k+1;t<=2*k;t++)
{
if(k*t%(t-k)==0)
{
x[cnt]=k*t/(t-k);
y[cnt]=t;
cnt++;
}
}
printf("%d\n",cnt);
for (t=0;t<cnt;t++)
{
printf("1/%d=1/%d+1/%d\n",k,x[t],y[t]);
}
}
return 0;
}
註意:在上面的源程式2中,x和y數組是定義的可變長數組,現在的C標準支持這樣的用法。
15-3 一數三平方
問題描述
有一類六位數,不僅它本身是平方數,而且它的前三位與後三位也都是平方數,這類數稱為“一數三平方數”。
輸入格式
無輸入
輸出格式
輸出所有的一數三平方數。每行輸出一個一數三平方數,具體格式參見輸出樣例。
輸入樣例
無輸入
輸出樣例
144400 : 12*12=144,20*20=400,380*380=144400
225625 : 15*15=225,25*25=625,475*475=225625
……
(1)編程思路。
如果程式對所有的六位數(100000~999999)進行窮舉,判斷這個六位數是否是一數三平方,顯然比較麻煩。
由於一個“一數三平方”數,其前三位與後三位一定都是平方數,因此,可以先求出999以內的所有的平方數,最多只有32個(即0的平方~31的平方,32的平方1024超過了3位)。定義一個數組int a[32]來保存這32個平方數。
程式中對這32個平方數兩兩組成的六位數進行窮舉判斷,顯然高三位必須為數組中a[10](即不小於10的平方100的數首位才不為0)之後的平方數。演算法描述為:
for(i=10;i<=31;i++)
for(j=0;j<=31;j++)
{
c=1000*a[i] +a[j]; // a[i]作為高三位、a[j]作為低三位構成六位數
if( c是平方數)
輸出相應信息並計數
}
(2)源程式。
#include <stdio.h>
#include <math.h>
int main()
{
int a[32],i,j;
long b,c,t;
for(i=0;i<=31;i++) // 統計出從0到999之內的所有平方數
a[i]=i*i;
for(i=10;i<=31;i++)
{
b=1000*a[i]; /*高三位數*/
for(j=0;j<=31;j++)
{
c=b+a[j]; /*六位數*/
t=sqrt(c); /*六位數開方*/
if(c==t*t) /*判斷六位數是否為平方數*/
{
printf("%d : %d*%d=%d,%d*%d=%d,%d*%d=%d\n",c,i,i,a[i],j,j,a[j],t,t,c);
}
}
}
return 0;
}