• 约瑟夫问题


    以下四种方法时间复杂度递减
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,k;
    bool v[301];
    int main()
    {
        while(scanf("%d%d",&n,&k)!=EOF)
        {
            if(!n) return 0;
            int now=-1,id=0,s=0;
            memset(v,0,sizeof(v));
            while(s<n-1)
            {
                while(id<k)
                {
                    now=(now+1)%n;
                    if(!v[now]) id++;
                }
                v[now]=true;
                s++;
                id=0;
            } 
            for(int i=0;i<n;i++)
             if(!v[i])
             {
                 printf("%d
    ",i+1);
                 break;
             }
        }
        
    }
    暴力枚举法
    蒟蒻的
    
    #include<cstdio>
    #include<algorithm>
    #define N 1000001
    using namespace std;
    int n,m;
    struct node
    {
        int l,r,sum;
    }tr[N*4];
    void build(int k,int l,int r)
    {
        tr[k].l=l; tr[k].r=r; tr[k].sum=r-l+1;
        if(l==r) return;
        int mid=l+r>>1;
        build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    }
    int query2(int k,int opl,int opr)
    {
        if(opl==tr[k].l&&opr==tr[k].r) return    tr[k].sum;
        int mid=tr[k].l+tr[k].r>>1;
        if(opr<=mid) return query2(k<<1,opl,opr);
        if(opl>mid) return query2(k<<1|1,opl,opr);
        return  query2(k<<1,opl,mid)+query2(k<<1|1,mid+1,opr);
    }
    int query1(int k,int l,int s)
    {
        if(tr[k].l==tr[k].r)     return tr[k].l;
        int mid=tr[k].l+tr[k].r>>1;
        int tmp=0;
        if(l<=mid) tmp=query2(k,l,mid);
        if(s<=tmp) query1(k<<1,l,s);
        else  query1(k<<1|1,max(mid+1,l),s-tmp);
    }
    void change(int k,int w)
    {
        if(tr[k].l==tr[k].r)
        {
            tr[k].sum=0;
            return;
        }
        int mid=tr[k].l+tr[k].r>>1;
        if(w<=mid) change(k<<1,w);
        else change(k<<1|1,w);
        tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
    }
    int query3(int k,int s)
    {
        if(tr[k].l==tr[k].r) return tr[k].l;
        int tmp=tr[k<<1].sum;
        if(s<=tmp) return query3(k<<1,s);
        return query3(k<<1|1,s-tmp);
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            if(!n) return 0;
            build(1,1,n);
            int pos=0,k,tot,tot2;
            for(int i=1;i<n;i++)
            {
                if(pos==n) pos=0;
                tot=query2(1,pos+1,n);
                if(tot>=m)  pos=query1(1,pos+1,m);
                else
                {
                    k=m-tot;
                    tot2=query2(1,1,n);
                    k%=tot2;
                    if(!k) k=tot2;
                    pos=query3(1,k);
                }
                change(1,pos);
            }
            printf("%d
    ",query3(1,1));
        }
        
    }
    
    线段树(做麻烦了)
    蒟蒻的线段树

    模拟所有人,出局所有人中的第几个人

    模拟场上还有几个人,出局场上第几个人

    http://www.cnblogs.com/IUUUUUUUskyyy/p/6216855.html

    #include <cstdio>
    
    using namespace std;
    
    struct node {
        int l,r,dis,mid;
        
        void mid_()
        {
            mid=(l+r)>>1;
        }
    };
    struct node tree[1000000*4+1];
    
    int n,m;
    
    inline void tree_up(int now)
    {
        tree[now].dis=tree[now<<1].dis+tree[now<<1|1].dis;
    }
    
    void tree_build(int now,int l,int r)
    {
        tree[now].l=l,tree[now].r=r;
        if(l==r)
        {
            tree[now].dis=1;
            return ;
        }
        tree[now].mid_();
        tree_build(now<<1,l,tree[now].mid);
        tree_build(now<<1|1,tree[now].mid+1,r);
        tree_up(now);
        return ;
    }
    
    int tree_out(int now,int ci)
    {
        if(tree[now].l==tree[now].r)
        {
            tree[now].dis=0;
            return tree[now].l;
        }
        if(tree[now<<1].dis<ci) ci=tree_out(now<<1|1,ci-tree[now<<1].dis);
        else ci=tree_out(now<<1,ci);
        tree_up(now);
        return ci;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        tree_build(1,1,n);
        int now=0;
        do
        {
            now=(now-1+m)%n;
            if(n>1) tree_out(1,now+1);
            else printf("%d ",tree_out(1,now+1));
        } while(--n);
        return 0;
    }
    myj大佬的线段树
    #include<cstdio>
    using namespace std;
    int main()
    {
        int n,k,ans=0;
        scanf("%d%d",&n,&k);
        for(int i=2;i<=n;i++)
         ans=(ans+k)%i;
        printf("%d",ans+1);
    }
    推公式

     某大佬的推导过程http://book.51cto.com/art/201403/433941.htm

    注意:此方法不能输出过程

  • 相关阅读:
    69期-Java SE-029_XML解析
    69期-Java SE-028_网络编程-3
    Django(46)drf序列化类的使用(ModelSerializer)
    Django(45)drf序列化类的使用(Serializer)
    Django(44)drf序列化源码分析
    Django(43)restful接口规范
    Django(42)DRF安装与使用
    Django(41)详解异步任务框架Celery
    Django(40)解决celery报错 No module named 'click._bashcomplete'
    Django(39)使用redis配置缓存
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6631427.html
Copyright © 2020-2023  润新知