BestCoder Round #75 King's Game

題目

爲了銘記歷史,國王準備在閱兵的間隙玩約瑟夫遊戲。它召來了 n(1\le n\le 5000)n(1≤n≤5000) 個士兵,逆時針圍成一個圈,依次標號 1, 2, 3 … n1,2,3…n。

第一輪第一個人從 11 開始報數,報到 11 就停止且報到 11 的這個人出局。

第二輪從上一輪出局的人的下一個人開始從 11 報數,報到 22 就停止且報到 22 的這個人出局。

第三輪從上一輪出局的人的下一個人開始從 11 報數,報到 33 就停止且報到 33 的這個人出局。

第 n - 1n−1 輪從上一輪出局的人的下一個人開始從 11 報數,報到 n - 1n−1 就停止且報到 n - 1n−1 的這個人出局。

最後剩餘的人是倖存者,請問這個人的標號是多少?

思路

設dp[i][j] 爲i個人 第一個人從j開始報號 的結果。
那麼dp[i][j] = (dp[i - 1][j + 1] + j) % i
因爲在dp[i][j] 下先刪除一個人第j個, 然後接着要刪除第(j+1)個所以是dp[i - 1][j + 1]. 而且本來開始的位置是0 現在變成了j所以要 +j.

代碼

#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;

int T; 
const int MAXN = 5010;
long long dp[MAXN]; 
int main() {
    scanf("%d",&T);

    for(int j = 5000;j >= 1;j --) {
        for(int i = 5000;i >= 1;i --) {
            dp[i] = (dp[i - 1] + j) % i; //使用類揹包手法優化
        }
    }


    while (T --) {
        int n;
        scanf("%d",&n);
        printf("%I64d\n",dp[n] + 1);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章