題目內容:
n(1< n <=5)個水手在島上發現一堆椰子,先由第1個水手把椰子分為等量的n堆,還剩下1個給了猴子,自己藏起1堆。然后,第2個水手把剩下的n-1堆混合后重新分為等量的n堆,還剩下1個給了猴子,自己藏起1堆。以后第3、4個水手依次按此方法處理。最后,第n個水手把剩下的椰子分為等量的n堆后,同樣剩下1個給了猴子。請用迭代法編程計算並輸出原來這堆椰子至少有多少個,n的值要求從鍵盤輸入。若輸入的n值超出要求的范圍,程序輸出”Error!”。
提示:分成的等量的堆數應該與水手的數量一致.
程序運行結果示例1:
Input n(1 < n <= 5):
5↙
y=3121.
程序運行結果示例2:
Input n (1 < n <= 5):
7↙
Error!
輸入提示信息: “Input n(1 < n <= 5):\n”
輸入格式: “%d”
輸出格式:”y=%d\n”
輸入錯誤提示信息:”Error!\n”
這是一道著名的數學問題,解題通式為:
y=a(a/m)n-1 -db/c
y ── 被分的椰子的總個數.
a ── 每次分的份數,
n ── 總共分的次數.
b ── 每次分a份后的余數.
c ── 每次分a份后拿走的份數.
d ── 每次分a份后拿走c份后,剩下再分的份數.
m── (a/d)的最大公約數.
迭代法實現
思路:
- 假設現在有五個人分一堆椰子,那么每個人都會分一次椰子,我們可以得知人數就是分椰子的次數
- 假設第一個人還沒分的時候椰子總共有y1個,那么第一個人分了之后,椰子總數y2=(y1-1)*(4/5);如果已知y2求y1,那么y1=(y2*5)/4+1。
- 我們知道椰子都是一個一個的,這就說明椰子數量是整數,判斷一個數是否是符合條件,我們僅需要判斷每次它被分之后是不是整數就ok。
- 為減少時間復雜度,我們選擇還原數量的方式迭代,設一個循環,循環變量為分了n次之后每一份的椰子數量,向上還原,判斷還原n層的過程中每次椰子的數量仍然是否是整數,如果不是,繼續外層循環,直到找到一個數能夠進行n次內層循環為止。
程序代碼(C語言):
#include<stdio.h>
int main()
{
int i, j, total, n;
printf("Input n(1<n<=5):\n");
scanf("%d", &n);
if (n <= 1 || n > 5)
{
printf("Error!\n");
}
else
{
i = 1;
while(1)
{
total = i;
for(j = 0; j < n; j++)
{
total = total * 5;
if(total % 4 != 0)
{
break;
}
total = total / 4;
total += 1;
}
if(j == n)
{
break;
}
i++;
}
printf("y=%d\n", total);
}
return 0;
}
遞歸實現
思路:
寫一個函數模擬分椰子操作,傳入分的椰子數量和分的人數,判斷椰子數量是否足夠支持到最后一個人分完,如果能返回一個真值,如果不能返回一個假值。
程序代碼(C語言):
#include <stdio.h>
int divide(int n, int m);
static int people;
int main()
{
int i;
int n;
printf("Input n(1<n<=5):\n");
scanf("%d", &n);
people = n;
if (n <= 1 || n > 5)
{
printf("Error!\n");
}
else
{
for (i = 1; ; i++)
{
if (divide(i, n))
{
printf("y=%d\n", i);
break;
}
}
}
return 0;
}
int divide(int n, int m)
{
if (n / people == 0 || n % people != 1)
return 0;
if (m == 1)
return 1;
return divide(n - n / people - 1, m - 1);
}