HDU2211 杀人游戏(数学)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2211
我们已知n和k。
那么能得到一些信息:
每一轮之后,剩下的人是n - n / k。
最后剩下k个人的时候,杀掉最后第k个人之后游戏结束。
那么在最后k个人中,最后一个人当前编号为k,我们要求的是他在上一轮的编号是多少,如果能求出,那么一直求到开始状态就能知道答案。
设当前编号为t,上一轮他的编号为x。需要找到t和x的关系。那么我们很容易列出一个表达式:t=x - x / k。但是可以发现, 这个式子是错的,当x整除k的时候,最后一个人被杀掉,那么也就没有t了。所以我们先去掉最后一个x,那么下一轮剩下的人是(x - 1) - (x - 1) / k + 1。所以得到t - 1=(x - 1) - (x - 1) / k。
化简得到x = (t * k - 1) / (k - 1),t * k可能会溢出。
所以再化简x = t + (t - 1) / (k - 1)。完毕。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<cstring>
#include<string>
#include<cctype>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<ctime>
#include<sstream>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int INF=1e9+7;
typedef pair<int,int> pii;
typedef long long ll;
int dfs(int n,int k){
    if(n==k)return k;
    int t=dfs(n-n/k,k);
    //return (t*k-1)/(k-1);t*k可能溢出
    return t+(t-1)/(k-1);
}
int main(){
//    freopen("D://input.txt","r",stdin);
    int T;scanf("%d",&T);
    while(T--){
        int n,k;scanf("%d%d",&n,&k);
        printf("%d\n",dfs(n,k));
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值