约瑟夫环问题

约瑟夫环问题其实非常简单,就是一圈人,每次挂掉第k个,下次从他的下一个开始数,再挂掉第k个,直到剩下一个为止。其中k可以是固定的,也可以是变化的。
约瑟夫问题模拟的复杂度较高,采用递推是比较合理的方式。
假设有n个人,每次杀死k个。
第一次杀死前编号如下:
0 1 2 … k-1 k k+1 … n-2 n-1 (1)
第一次杀死后编号如下:
0 1 2 … k-2 k k+1 … n-2 n-1 (2)
那么下一次开始的时候就要这么看这个编号:
k k+1 k+2 … n-2 n-1 0 1 2 … k-2 (3)
将此编号重新排列:
0 1 2 … n-2-k n-1-k n-k … n-2 (4)

对比(3) (4)可以推导出公式:
x’=(x+k) mod n
其中x’是上一轮的编号,x是后一轮的编号,k为上一轮杀死的人,n为上一轮的人数。

例如:http://acm.hdu.edu.cn/showproblem.php?pid=5643在这里有汉语翻译http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=677&pid=1004

代码如下:
/***************************************************************

File Name: 1004.cpp
Author: wxc575843
Mail: wxc575843@163.com
Created Time: 六 3/12 21:59:54 2016
**************************************************************/

#include<iostream>
using namespace std;

int dp[5000];

void solve(){
    dp[0]=0;
    int n;
    cin>>n;
    for(int i=1;i<n;i++){
        dp[i]=(dp[i-1]+n-i)%(i+1);
    }
    dp[n-1]++;
    cout<<dp[n-1]<<endl;
}

int main(){
    int n;
    cin>>n;
    while(n--){
        solve();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值