1. 程式人生 > >水手分椰子——迭代法、遞迴解題

水手分椰子——迭代法、遞迴解題

題目內容:

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)的最大公約數.

迭代法實現

思路:

  1. 假設現在有五個人分一堆椰子,那麼每個人都會分一次椰子,我們可以得知人數就是分椰子的次數
  2. 假設第一個人還沒分的時候椰子總共有y1個,那麼第一個人分了之後,椰子總數y2=(y1-1)*(4/5);如果已知y2求y1,那麼y1=(y2*5)/4+1。
  3. 我們知道椰子都是一個一個的,這就說明椰子數量是整數,判斷一個數是否是符合條件,我們僅需要判斷每次它被分之後是不是整數就ok。
  4. 為減少時間複雜度,我們選擇還原數量的方式迭代,設一個迴圈,迴圈變數為分了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);
}