递归+整除方程:hdu 2211 杀人游戏

这道题做的人不多,而且网上凡是用递归解决的都缺少推导过程,笔者安安静静的动笔算了一遍,发现这道题的两个关键点——这里写图片描述
希望阅读者珍惜笔者的劳动成果,转载请注明出处:

http://blog.csdn.net/u012717411

先说递归思想:递推关系+边界条件,二者缺一不可。这道题的递推关系是根据前一轮胜利者的编号确定当前轮胜利者的编号,一直递推下去到最后一轮(也就是边界条件),胜利者在1,2,3,……,k-1,k的第k个位置上。即n==k时,返回k.

再说整除方程(返回值的确定)。

如果你查阅相关结题报告,凡是递归解决的无外乎这样一段话:
这里写图片描述
这句话只是结论呦,推导看我的吧~

设上一轮胜利者的编号为x,当前轮胜利者的编号为y,容易推到得到这样的一个方程:y=y/k+x
式子意义是当前编号=这一轮在y之前被杀死的数量+上一轮在y之前剩下的数量x
注意,这可不是一般的方程哦,/表示的是整除,不要左右同×k,结果不等价的。
这样的方程笔者姑且叫她整除方程吧,利用不等式求解。求解思路如下:
●Step1 首先观察到y无法直接求解,不妨先求y/k,设m=y/k,则y=m+x(x已知),问题转化为求整除结果m.
●Step2 由y/k=m有,m·k+1<=y<=m·k+(k-1).为什么是m·k+1<=y而不是m·k<=y,因为y表示的是当前这轮胜利者的编号,不到最后一轮不会出现y%k==0的情况(最后一轮已经被返回了)。令y=m+x,代入得到
m·k+1<=m+x<=m·k+(k-1),原不等式组等价于
m·(k-1)<=x-1<=m·(k-1)+(k-2).
看出来没有??!!!把她反一下就可以表示为m=(x-1)/(k-1),两者表示的含义是不是等价的????!!!!Yes!!
那么m就求出来啦.则y=y/k+x=m+x=(x-1)/(k-1)+x了,参考递归代码:

参考代码+部分注释

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <climits>
#define eps 1e-8
using namespace std;
typedef long long ll;
const int INF=INT_MAX;
const int maxn = 110;
int n,k;
int recursion(int n,int k)
{
    if(n==k) return k;       //边界条件
    int x=recursion(n-n/k,k);//胜利者在下一个子序列的编号记为x
    return (x-1)/(k-1)+x;    //那么这一轮的编号y=y/k+x;
}
int main()
{
 //  freopen("input.txt","r",stdin);
   int T;cin>>T;
   while(T--){
    cin>>n>>k;
    cout<<recursion(n,k)<<endl;;
   }
   return 0;
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值