1. 程式人生 > >[CSP]201712-2 遊戲 暴力+(以此為例)約瑟夫環的遞推

[CSP]201712-2 遊戲 暴力+(以此為例)約瑟夫環的遞推

愚蠢的看錯題了。中文讀題能力還不如英文,有待提升。

所以這道題用普通的陣列模擬操作就可以了。總之跟暴力模擬的約瑟夫環沒什麼區別。

可以用next陣列模擬指標做資料結構,但是資料範圍不大的情況下不建議這麼寫,維護一個指標環寫起來還是比較麻煩的。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1005;
bool survive[MAXN];

int solve(int n, int k)
{
    for(int i = 0; i < n; i++)
    {
        survive[i] = true;
    }
    int cnt = 0, snum = n;
    int idx = -1;
    while(snum)
    {
        idx = (idx + 1) % n;
        if(survive[idx] == true){
            cnt++;
            if(cnt % k == 0 || cnt % 10 == k){
                survive[idx] = false;
                //printf("%d\n", idx+1);
                snum--;
            }
        }
        if(snum == 1)break;
    }
    for(int i = 0; i < n; i++)if(survive[i] == true)return i;
}
int main()

{
    int n, k;
    scanf("%d%d", &n, &k);
    int ans = solve(n, k);
    printf("%d\n", ans+1);
    return 0;
}

但是突然想到比得十分GG的藍橋杯國賽,必須要記錄一下約瑟夫環的標準數學(找規律)解法。

將k固定,設解ANS[n,k] = ans(n)

具有m個數的m約瑟夫環中,刪除一個數之後,相當於重新標號後的m-1約瑟夫環問題。

設從a(1)開始的m約瑟夫環答案為ans(m) = s,在m+1約瑟夫環中,由於經歷了重新標號,m中的標號a(i)應該為a((k+i)%(m+1)) ,所以答案下標也要從s移動到(s+k)%(m+1).

公式:ans(1) = 1, ans(m+1) = (ans(m)+k)%(m+1)。程式碼如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
//標準約瑟夫環,非此題題解
int main()
{
    int n, k;
    int i, s = 0;
    scanf("%d%d", &n, &k);
    for (i = 2; i <= n; i++)
    {
        s = (s + k) % i;
        //printf("%d\n",s+1);
    }
    printf ("%d\n", s+1);
}