杭电2211杀人游戏

其实此题在测试数据小的情况下可以用解决约瑟夫环的方法

但是因为此题数据很大(2^31),所以用解约瑟夫的方法肯定会爆内存

解题的关键在于找出每次操作前后编号位置的变化关系

-----------------------------------------------------------------------------------------------------------------------------------------

采用递归的思路,任取一轮开始讨论,假设此时剩下m人

1,2,3,4,5......m

我们需要推出上一次第m个人的位置,由于是每第k个就杀掉,所以要还原上一次的队列就必须每两k-1个人就要补上1个人,

当前第m人前面有m-1人,所以要补上(m-1)/(k-1)个人,因此当前第m人在上一次队列中的位置是(m-1)/(k-1)+m

至此,关系已经推出,接下来是代码实现

#include<stdio.h>
int main()
{
	int  dfs(int n,int k);
	int T;
	int n,k;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&k);
		printf("%d\n",dfs(n,k));
	}
	return 0;	
}
int dfs(int n,int k)
{
	int num;
	if(n==k)
	{
		return k;
	}
	num=dfs(n-n/k,k);
	return ((num-1)/(k-1)+num);
}


-------------------------------------------------------------------------------------------------------------------------------------------

做此题时无意间想出的用数组解决约瑟夫环的方法(之前只学过链表的),不知道是不是很普遍的,

主要是利用两个数组交替存放剩下的队列,在此贴出来水水

#include<stdio.h>
#include<stdlib.h>
int a[100000000];
int b[100000000];
int main()
{
    void kkk(int a[1],int b[],int na,int k);
    int T,n,k;
    scanf("%d",&T);
    int i,j,na,nb;
    while(T--)
    {
		scanf("%d%d",&n,&k);
       for(i=1;i<=n;++i)
       {
          a[i]=b[i]=i;
       }
		kkk(a,b,n,k);
    }
    return 0;
}
void kkk(int a[],int b[],int na,int k)
{
    int nb=1;
    int i;
    for(i=1;i<=na;++i)
    {
       if(i%k!=0)
       {b[nb]=a[i];nb++;}
    }
    nb--;
    if(nb==k)
    {
        printf("%d\n",b[k]);
        return;
    }
    else
    {
       kkk(b,a,nb,k);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值