pku2244约瑟夫环问题

【题意】

n个城市(标号1,2,....,n)轮流断网,先停1号城市,然后每m个城市断网,断了的就不用计入在内了。

 

【分析】

约瑟夫环杀人游戏的一个变种。

自己总算能用之前的公式套了。

我们已知的结论是:

f[i]表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是f[n],递推公式:
f[1]=0;
f[i]=(f[i-1]+m)%i;  (i>1) //注意这里%i,i表示当前算的数,计算f[2],则i=2,计算f[3],则i=3,开始我搞错了。

 

本题1号城市首先断网,所以对于给定的n,我只需要计算出最小的m,使得f[n-1]=0即可;

道理是:1号城市已经断网了,再以后的循环就不会再有1介入,要使2号城市最后断网(最后胜利者)也就是使剩下n-1个城市的第一个城市成为胜利者,而我们公式里的编号是从0开始的,第一个城市的编号在答案里就是0;

依据上面的分析,题目n,3<=n<150,我们可以先处理出所有的n,对于每一个n,枚举m,当f[n]=0时,我们就得到了结果,保存之,具体见代码。

 

【代码】

 

/*2244 Accepted 136K 16MS C++ 518B 2011-01-19 20:45:46 */
#include<stdio.h>
#include<string.h>
int f[152],ans[152];
void Init(){
    int m,i,j,count=0,flag=0;
    memset(f,0,sizeof(f)); f[1]=0;
    for(i=2;i<150;i++){
        for(m=2;;m++){
            for(j=2;j<=i;j++)
                f[j]=(f[j-1]+m)%j; //j,当前人数;
            if(f[i]==0){ ans[i+1]=m; break; }
        }
    }       
}           
int main()
{
    int k;
    Init();
    while(scanf("%d",&k),k)
        printf("%d/n",ans[k]);
}   

 

后来找了网上的一篇题解:

http://brianyang1106.blog.163.com/blog/static/137602892201002734755225/

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值