K. Let the Flames Begin(约瑟夫环 第m个死)

109 篇文章 0 订阅

原题: http://codeforces.com/gym/101955/problem/K

题意:

给出n个人的环,约瑟夫环背景,求第 m m m个死的位置。

解析:

先看一遍我的这篇约瑟夫环的博客,就知道怎么做了。

https://blog.csdn.net/jk_chen_acmer/article/details/80083118

其实第 m m m个死也可以从那个式子推过来, n + 1 n+1 n+1个人第 m m m个死的位置相当于 n n n个人第 m − 1 m-1 m1个死的位置转k个下标。即 A ( n , m ) = ( A ( n − 1 , m − 1 ) + k ) % n A(n,m)=(A(n-1,m-1)+k)\%n A(n,m)=(A(n1,m1)+k)%n

当m较小的时候直接推就行了。


对于 m = 1 e 18 , k = 1 e 6 m=1e18,k=1e6 m=1e18,k=1e6的数据,显然 A ( n , m ) = ( A ( n − 1 , m − 1 ) + k ) % n A(n,m)=(A(n-1,m-1)+k)\%n A(n,m)=(A(n1,m1)+k)%n的这个 % n \%n %n在很多时候没有用处。

A + x k &lt; n + x x ( k − 1 ) &lt; n − A x &lt; n − A ( k − 1 ) A+xk&lt;n+x\\x(k-1)&lt;n-A\\x&lt;\dfrac{n-A}{(k-1)} A+xk<n+xx(k1)<nAx<(k1)nA

处理一下就可以了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long

LL F(LL n,LL m,LL k){
    if(m==1)return (k-1)%n;
    return (F(n-1,m-1,k)+k)%n;
}

int main(){
    int t,cas=0;scanf("%d",&t);
    while(t--){
        printf("Case #%d: ",++cas);
        LL n,m,k;scanf("%lld%lld%lld",&n,&m,&k);
        if(k==1){
            printf("%lld\n",m);
            continue;
        }
        if(m<=1e6)printf("%lld\n",F(n,m,k)+1);
        else{
            LL ct=n-m+1;
            LL val=(k-1)%(ct);
            LL now=1;
            while(now<m){
                if(val+k>=ct+1){
                    ct++;
                    val=(val+k)%ct;
                    now++;
                    continue;
                }
                LL x=(ct-val-1)/(k-1);
                x=min(x,m-now);
                now+=x;
                val+=k*x;
                ct+=x;
            }
            printf("%lld\n",val+1);
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值