POJ1012 Joseph解题报告

_考查点:

约瑟夫问题的变形。


_思路:

这里是要知道每一次出局的人的范围。而最初的约瑟夫问题只能知道最后一个出局的人的编号。

我所知道的有两种方法(均是数学方法)一个是暴力枚举加打表(0MS过掉),一个不用打表(论证了m满足一定条件不用暴力枚举)。

(第二个方法未理解,以后加上)。我们先说第一个方法,我们知道前k次killing,killed_man满足是(编号0~ 2 * k - 1)最后的k个人

这样的m就符合要求。那么我们不去关心kill掉一个人后,他后面的人原来的编号(这个题不关心编号的问题)。

只需要满足每一次(一共k次)killing是在第k个人(编号k - 1)之后就行。那么每杀掉一个,

就将被杀的那个人(设编号为killed)后面的人的编号依次变为killed,killed + 1,...,2 * k - 1 - i(i为被杀次数). 

虽然总人数在减小,我们只需要满足前k次killing的是在编号k - 1之后就行了。

那么就有关系式f [ i ] = ( f[i - 1] - 1 + m) % (2 * k - i).

这个公式其实就是在求杀掉一个人后,下一个被杀的人的编号(也可以说位置,我们关心的就是这个)。

为何是 f[i - 1] - 1?你想想新的环就是一个数组中间删掉了一个元素,他后面的元素一次往左移动一个位置。

移动后,对于新一轮的被杀游戏,开始的位置就是f[ i - 1] - 1的下一个元素,所以就是f[i - 1] - 1. 而分母(2 * k - i)为当前轮的总人数。

要是看不懂(我表达能力还待提高~~),就google、百度吧,这是一大法宝。

(留下评论也行,咱们一起讨论、讨论,互相学习,我也是goole之后才懂的这题的方法,然后自己推导出来这个公式)


_提交情况:

一次就AC了(用的打表)。


_收获:

知道了自己的数学是有多差。得好好做做思维的体操才行啊。


-AC Codes:

#include <cstdio>


int array[14] = {0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881};


int main() {
    int k;
    while (scanf("%d", &k) != EOF && k) {
        printf("%d\n", array[k]);
    }
}

/*

上面数组的结果来自这串代码:

#include <cstdio>
//#define GANGAN

int main() {
#ifdef GANGAN
freopen("1012_in.txt", "r", stdin);
freopen("1012_out.txt", "w", stdout);
#endif
int i, m, k;

while (scanf("%d", &k) != EOF && 0 != k) {
        int m, flag;
        for (m = k; ; m++) {//以0为起始编号能够避免讨论m为(2 * k)时的麻烦
            flag = 1;
            int killed = 0;
            for (int i = 0; i < k; i++) {
                killed = (killed - 1 + m) % (2 * k - i);
                if (killed < k) {
                    flag = 0;
                    break;
                }
            }
            if (flag) {
                break;
            }
        }
        printf("%d,", m);
}
return 0;
}

//*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值