约瑟夫问题(Josephus_problem) 终极解析

本文介绍了一种解决约瑟夫环问题的高效数学方法,通过数学推导避免了传统循环模拟方法的时间复杂度过高的问题。适用于求解大规模数据集下的最后一个存活者编号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



Josephus_problem数学终极解法


思想来源于:http://en.wikipedia.org/wiki/Josephus_problem ,对Josephus_problem问题的阐述。

以hdu2925题为例

循环模拟方法:严重超时(代码如下)

#include<iostream>

using namespace std;

struct People

{

         intnum;

         boolisLife;

};

People peopleArr[1000];

int main()

{

         freopen("input.txt","r",stdin);

   int sumPerson,count,signTime,deadNum,i;

         while(scanf("%d%d",&sumPerson,&count)== 2 && sumPerson && count)

         {

       signTime = 0;

                  deadNum= 0;

                  for(i = 1 ; i <= sumPerson; i ++)

                  {

           peopleArr[i].num = i;

                          peopleArr[i].isLife= true;

                  }

       while(deadNum != sumPerson-1)

                  {

           for(i = 1;i <= sumPerson; i ++)

                          {

                 if(peopleArr[i].isLife) 

                                    {

                                             signTime ++;

                                             if(signTime % count == 0) 

                                             {

                                                      peopleArr[i].isLife = false;

                                                      deadNum ++;

                                                      //signTime = 0;

                                             }

                                             if(deadNum = sumPerson -1)

                                                     break;

                                    }

                          }

                  }

       for(i = 1; i <= sumPerson; i ++)

                  {

                          if(peopleArr[i].isLife)

                                   //cout<<sumPerson<<""<<count<<" "<<peopleArr[i].num<<endl;

                                   printf("%d%d %d\n",sumPerson,count,peopleArr[i].num);

                  }

 

         }

         return0;

}

以上时间复杂度高达O(nm),当n,m非常大(例如上百万,上千万)的时候,其实是没有办法在短时间内出结果的。

有的问题仅仅是要求出最后的胜利者的序号,而不是要读者模拟整个过程。

因此如果要追求效率,就要打破常规,实施一点数学策略。


#include<iostream>
using namespace std;
int f[1000010];
int main()
{
freopen("input.txt","r",stdin);
int N,D,W,i;
    while(scanf("%d%d",&N,&D) &&(N+D))
{
f[1] = 0;               
for(i = 2; i <= N; i ++)    //从零开始报数
{
f[i] = (f[i-1] + D)%i;  //数学推导当i个人数数时,赢家f[i]与f[i-1]有数学关系
}
printf("%d %d %d\n",N,D,f[N]+1);
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiangyong58

喝杯茶还能肝到天亮,共同进步

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值