ACM模版——约瑟夫问题(出列顺序 + 最后一个)

简介: ACM模版——约瑟夫问题(出列顺序 + 最后一个)

最后一个:针对 n 范围比较大的解析


0、在公式:ans=(ans+m)%i 的基础上...当i很大,ans 和 m 都比较小的时候(i>>ans 和 m)。ans 每次增加的其实是 m。而这个增加次数可以算出来。所以...


1、当 ans + m >= i 时,普通递推。


2、当 ans + m < i 时,设增加次数为 x 次(代码中为:step 变量)。满足 ans + x * m < i + x - 1。


Ps:之所以是 x - 1,是因为 ans + m < i,ans + m + (x-1) * m < i + x -1。


3、由 2 得:x < (i - ans - 1) / (m - 1);x = ceil((i - ans - 1) / (m - 1)) - 1。


4、由 3 得:ans += x * m,i += x。


5、但如果 i 增加的总次数 (i + x) > n 了,那么最终结果应增加 (n - i + 1) * m 次,而不是 i+x 次。


/

#include<bits/stdc++.h>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof a)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int main()
{
    ll n,m;
    while(~scanf("%lld%lld",&n,&m))
    {
        /* 最后一个:针对n范围比较小的解决方案 */
        // 编号从0开始
//        int ans=0;
//        for(int i=2;i<=n;i++)
//            ans=(ans+m)%i;
//        printf("%d\n",ans); // 输出的是数组下标
        /* 最后一个:针对n范围比较大的解决方案 HDU3089 */
        // 编号从0开始
//        ll ans=0,step=0;
//        if(m==1) ans=n-1;
//        else if(n==1) ans=0;
//        else
//        {
//            for(ll i=2;i<=n;)
//            {
//                if(ans+m<i)
//                {
                    step=(i-1-ans)%(m-1)?(i-1-ans)/(m-1):(i-1-ans)/(m-1)-1; // 等价下面这行代码
//                    step=ceil((i-1-ans)*1.0/(m-1))-1;
//                    if(i+step>n)
//                    {
//                        ans+=(n-i+1)*m; // (n-i+1)次
//                        break;
//                    }
//
//                    ans+=step*m;
//                    i+=step;
//                }
//                else
//                    ans=(ans+m)%i++;
//            }
//            ans%=n;
//        }
//
//        printf("%lld\n",ans+1); // 输出的是数组下标
        /* 出列顺序:针对出列顺序解决方案O(n*m) */
        // 编号从0开始
//        int idx=0,cnt=1,pout=0,vis[n+10];
//        mem(vis,0);
//        while(pout!=n) // out人数是否满
//        {
//            if(1==vis[idx]) // 已out
//            {
//                idx=(idx+1)%n;
//                continue;
//            }
//
//            if(cnt%m==0) // 准备out
//            {
//                vis[idx]=1;
//                pout++;
//                printf("%d\n",idx+1);
//            }
//
//            idx=(idx+1)%n; // 继续报数
//            cnt++;
//        }
        /* 针对出列顺序解决方案O(n*(logn)^2) */
        // 待更新...
    }
    return 0;
}
目录
相关文章
|
7月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-101 图形显示
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-101 图形显示
31 0
|
4月前
|
C#
【Azure Developer】解答《美丽的数学》一书中P120页的一道谜题:寻找第四个阶乘和数
【Azure Developer】解答《美丽的数学》一书中P120页的一道谜题:寻找第四个阶乘和数
|
7月前
|
Java C++ Python
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-161 Abbott’s Revenge(C++写法)
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-161 Abbott’s Revenge(C++写法)
157 42
ACM刷题之路(三)dfs+排列 第K个幸运排列
ACM刷题之路(三)dfs+排列 第K个幸运排列
|
7月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-79 删除数组零元素
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-79 删除数组零元素
40 0
|
7月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-627 排列
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-627 排列
48 0
ACM刷题之路(九)数论-逆序组 交换座位
ACM刷题之路(九)数论-逆序组 交换座位
|
存储 算法 JavaScript
未完成--字典--《数据结构与算法》
未完成--字典--《数据结构与算法》
68 0
|
算法 Java
『牛客|每日一题』模板队列
基础算法无论在研究生面试还是求职面试都是十分重要的一环,这里推荐一款算法面试神器:牛客网-面试神器;算法题只有多刷勤刷才能保持思路与手感,大家赶紧行动起来吧(温馨提示:常见的面试问答题库也很nice哦 https://www.nowcoder.com/link/pc_csdncpt_ll_sf
60 0
|
算法
每日一题冲刺大厂提高组第二十二天 无序字母对
大家好,我是泡泡,给大家带来每日一题的目的是为了更好的练习算法,我们的每日一题为了让大家练到各种各样的题目,熟悉各种题型,一年以后,蜕变成为一个不一样的自己!
93 0