1. 程式人生 > >Bailian2746 約瑟夫問題

Bailian2746 約瑟夫問題

2746:約瑟夫問題
總時間限制: 1000ms 記憶體限制: 65536kB
描述
約瑟夫問題:有n只猴子,按順時針方向圍成一圈選大王(編號從1到n),從第1號開始報數,一直數到m,數到m的猴子退出圈外,剩下的猴子再接著從1開始報數。就這樣,直到圈內只剩下一隻猴子時,這個猴子就是猴王,程式設計求輸入n,m後,輸出最後猴王的編號。
輸入
每行是用空格分開的兩個整數,第一個是 n, 第二個是 m ( 0 < m,n <=300)。最後一行是:
0 0
輸出
對於每行輸入資料(最後一行除外),輸出資料也是一行,即最後猴王的編號
樣例輸入
6 2
12 4
8 3
0 0
樣例輸出
5
1
7

問題連結

Bailian2746 約瑟夫問題
問題簡述:(略)
問題分析
    約瑟夫問題有2種解法,一是模擬法,二是數學法。
    數學法需要數學推導,這裡略去推導過程,只給出程式。
    模擬法可以使用多種資料表示,例如資料結構和STL,這裡給出用陣列進行模擬的方法。由於邏輯簡單,時間上應該更快一些。
程式說明:(略)
參考連結:(略)
題記:(略)

AC的C語言程式(模擬法)如下:

/* Bailian2746 約瑟夫問題 */

#include <stdio.h>

#define N 300
int a[N];

int main(void)
{
    int n, k, m, pos, cnt;

    while(scanf("%d%d", &n, &m) != EOF && (n || m)) {
        for( k = 0 ; k < n ; k++ )
            a[k] = k+1;

        for( k = 1, pos = 0; k < n; k++) {
            cnt = 0;
            while( cnt < m ) {
                while( a[pos] == 0 )
                    pos++, pos %= n;
                if(++cnt < m)
                    pos++, pos %= n;
            }
            a[pos] = 0;
            pos++, pos %= n;
        }
        /* 輸出結果 */
        for(k = 0; k < n; k++)
            if(a[k]) {
                printf("%d\n", a[k]);
                break;
            }
    }

    return 0;
}

AC的C語言程式(數學法)如下:

/* Bailian2746 約瑟夫問題 */

#include <stdio.h>

int main(void)
{
    int n, m, i, s=0;
    while(scanf("%d%d", &n, &m) != EOF && (n || m)) {
        s=0;
        for (i = 2; i <= n; i++)
            s = (s + m) % i;
        printf ("%d\n", s + 1);
    }

    return 0;
}