例8 尼科徹斯定理 題目描述 尼科徹斯定理可以敘述為:任何一個整數的立方都可以表示成一串連續的奇數的和。需要註意的是,這些奇數一定是連續的,如:1,3,5,7,9,…。 例如,對於整數5,5*5*5=125=21+23+25+27+29。 對於整數6,216=31+33+35+37+39+41, 也 ...
例8 尼科徹斯定理
題目描述
尼科徹斯定理可以敘述為:任何一個整數的立方都可以表示成一串連續的奇數的和。需要註意的是,這些奇數一定是連續的,如:1,3,5,7,9,…。
例如,對於整數5,5*5*5=125=21+23+25+27+29。
對於整數6,216=31+33+35+37+39+41,
也可以表示為216=7+9+11+13+15+17+19+21+23+25+27+29。
請你編寫程式對這個定理進行驗證。
輸入格式
一個整數n(2≤n≤1000)。
輸出格式
將n的立方表示為一串連續的奇數的和,具體格式見輸出樣例。若有多種表示方式,任意輸出一種即可。
輸入樣例
29
輸出樣例
29*29*29=24389=813+815+817+819+821+823+825+827+829+831+833+835+837+839+841+843+845+847+849+851+853+855+857+859+861+863+865+867+869
(1)編程思路1。
先計算輸入數n的立方num,然後從1(用變數i記錄)開始累計和sum,累計每次j加2保證下個數也為奇數,如果累加和sum大於立方數num時,跳出本次迴圈,進行下一次的嘗試(i=3或5、7、…開始累積和)。當找到後,記錄開始位置(即i),結束位置(即j),輸出。
程式寫成一個嵌套的二重迴圈。外迴圈i控制累計和的起點,內迴圈累計i、i+2、i+4、…的和。
(2)源程式1。
#include<stdio.h>
int main()
{
int n,num,sum,i,j,k,flag;
while(1)
{
scanf("%d",&n);
if(n==0) break;
num = n * n * n;
flag=0;
for(i=1; i<num && flag==0; i=i+2)
{
sum=0;
for(j=i; j<num; j=j+2)
{
sum += j;
if(sum == num)
{
printf("%d*%d*%d=%d=%d",n,n,n,num,i);
for (k=i+2; k<=j;k+=2)
printf("+%d",k);
printf("\n");
flag=1;
break;
}
else if (sum > num)
break;
}
}
}
return 0;
}
(3)編程思路2。
源程式1的思路是通過試探的方法來驗證尼科徹斯定理,採用二重迴圈實現。
實際上,n的立方一定可以表示為一個等差數列的各項和,該等差數列的首項為n*n-n+1,公差為2,項數為n。
按等差數列的求和公式知該數列的和為:
[(n*n-n+1)+( n*n-n+1)+ 2 (n-1)]*n/2 =n*n*n
因此,直接用迴圈輸出這個等差數列的各項即可。
(4)源程式2。
#include<stdio.h>
int main()
{
int n,a,i;
while(1)
{
scanf("%d",&n);
if(n==0) break;
// 輸出等差數列,首項為n*n-n+1,公差為2,項數為n
a=n*n-n+1;
printf("%d*%d*%d=%d=%d",n,n,n,n*n*n,a);
for (i=1; i<n;i++)
printf("+%d",a+i*2);
printf("\n");
}
return 0;
}
習題8
8-1 谷角猜想
題目描述
日本數學家谷角靜夫在研究自然數時發現了一個奇怪現象:對於任意一個自然數 n ,若 n 為偶數,則將其除以 2 ;若 n 為奇數,則將其乘以 3 ,然後再加 1 。如此經過有限次運算後,總可以得到自然數 1 。人們把谷角靜夫的這一發現叫做“谷角猜想”。
請你編寫程式對這個猜想進行驗證。
輸入格式
一個自然數n。
輸出格式
把 n 經過有限次運算後,最終變成自然數 1 的全過程輸出。具體格式見輸出樣例。
輸入樣例
34
輸出樣例
34/2=17
17*3+1=52
52/2=26
26/2=13
13*3+1=40
40/2=20
20/2=10
10/2=5
5*3+1=16
16/2=8
8/2=4
4/2=2
2/2=1
(1)編程思路。
定義迭代變數為n,按照谷角猜想的內容,可以得到兩種情況下的迭代關係式:當 n 為偶數時,n=n/2 ;當 n 為奇數時, n=n*3+1 。
這就是需要電腦重覆執行的迭代過程。這個迭代過程需要重覆執行多少次,才能使迭代變數 n 最終變成自然數 1 ,這是我們無法計算出來的。因此,還需進一步確定用來結束迭代過程的條件。由於對任意給定的一個自然數 n ,只要經過有限次運算後,能夠得到自然數 1 ,從而完成驗證工作。因此,用來結束迭代過程的條件可以定義為: n==1 。
(2)源程式。
#include<stdio.h>
int main()
{
unsigned int data;
scanf("%d",&data);
while(data!=1)
{
if((data%2==0))
{
printf("%d/2=%d\n",data,data/2);
data/=2;
}
else
{
printf("%d*3+1=%d\n",data,data*3+1);
data=data*3+1;
}
}
return 0;
}
8-2 四方定理
題目描述
數論中著名的“四方定理”是:所有自然數至多只要用四個不小於0的整數的平方和就可以表示。
編寫一個程式驗證此定理。
輸入格式
一個自然數n。
輸出格式
把自然數 n 表示為四個數的平方和。具體格式見輸出樣例。
輸入樣例
147
輸出樣例
7*7+7*7+7*7+0*0=147
8*8+7*7+5*5+3*3=147
9*9+5*5+5*5+4*4=147
9*9+7*7+4*4+1*1=147
9*9+8*8+1*1+1*1=147
11*11+4*4+3*3+1*1=147
11*11+5*5+1*1+0*0=147
12*12+1*1+1*1+1*1=147
(1)編程思路。
對於待驗證的自然數n,用四個變數i、j、k、l採用試探的方法,窮舉進行計算,滿足要求(i *i + j * j + k * k + l * l == n)時輸出計算結果。
在窮舉時,不妨設i≥j≥k≥l。因此,窮舉的範圍可確定為:
1 ≤ i ≤ n/2
0 ≤ j ≤ i
0 ≤ k ≤ j
0 ≤ l ≤ k
(2)源程式。
#include<stdio.h>
int main()
{
int n,i,j,k,l;
scanf("%d",&n);
for (i = 1; i <= n/2; i++) // 對i,j,k,l進行窮舉
for (j = 0; j <= i; j++)
for (k = 0; k <= j; k++)
for (l = 0; l <= k; l++)
if (i *i + j * j + k * k + l * l == n)
{
printf("%d*%d+%d*%d+%d*%d+%d*%d=%d\n",i,i,j,j,k,k,l,l,n);
}
return 0;
}
8-3 卡布列克運算
問題描述
所謂卡布列克運算,是指任意一個四位數,只要它們各個位上的數字不全相同,就有這樣的規律:
(1)把組成這個四位數的四個數字由大到小排列,形成由這四個數字構成的最大的四位數;
(2)把組成這個四位數的四個數字由小到大排列,形成由這四個數字構成的最小的四位數(如果四個數字中含有0,則此數不足四位);
(3)求出以上兩數之差,得到一個新的四位數。
重覆以上過程,總能得到最後的結果是 6174。
例如,n= 3280,驗證結果為:8320-238=8082 8820-288=8532 8532-2358=6174
編寫一個程式對卡布列克運算進行驗證。
輸入數據
一個各位上的數字不全相同的四位數n。
輸出要求
把 n 經過有限次卡布列克運算後,最終變成6174的全過程輸出。具體格式見輸出樣例。
輸入樣例
2019
輸出樣例
9210-129=9081
9810-189=9621
9621-1269=8352
8532-2358=6174
YES
(1)編程思路。
為實現驗證程式,編寫4個函數。
void parse_sort(int each[],int num) 將num分解為各位數字併排序後存入數組each[]中。
int minD(int each[]) 求數組each中的4個數字可組成的最大數。
int maxD(int each[]) 求數組each中的4個數字可組成的最小數。
int pow10_int(int n) 求10的N次方。
(2)源程式。
#include <stdio.h>
#define N 4
int pow10_int(int n); // 求10的N次方
void parse_sort(int each[],int num); // 把num分解各個位上的數後存入數組each[]中
int minD(int each[]); // 求數組each可組成的最大數
int maxD(int each[]); // 求數組each可組成的最小數
int main()
{
int number,max,min;
int each[N];
scanf("%d",&number);
while(number!=6174)
{
parse_sort(each,number);
max=maxD(each);
min=minD(each);
number=max-min;
printf("%d-%d=%d\n",max,min,number);
}
printf(" YES\n");
return 0;
}
int pow10_int(int n) // 求10的N次方的函數
{
int sum=1;
for(int i=0;i<n;i++)
sum=sum*10;
return sum;
}
void parse_sort(int each[],int num) // 把num分解各個位上的數後存入數組each[]中
{
int m,i,j,t;
for (i=0;i<N;i++)
each[i]=0;
i=0;
while(num!=0)
{
m=num%10; num=num/10;
each[i++]=m;
}
for(i=0;i<N-1;i++)
for (j=0;j<N-1-i;j++)
if (each[j]>each[j+1])
{
t=each[j];
each[j]=each[j+1];
each[j+1]=t;
}
}
int minD(int each[]) // 求數組each可組成的最大數
{
int sum=0,i;
for(i=0;i<N;i++)
sum+=each[i]*pow10_int( (N-1-i) );
return sum;
}
int maxD(int each[]) // 求數組each可組成的最小數
{
int sum=0,i;
for(i=0;i<N;i++)
sum=sum+each[i]*pow10_int(i);
return sum;
}