• 「模拟8.23」one递推,约瑟夫


    前置芝士约瑟夫问题

    这样大概就是板子问题了

    考场的树状数组+二分的60分暴力???

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 #define MAXN 11000001
     4 int c[MAXN];
     5 int lowbit(int x){return x&(-x);}int n;
     6 void add(int x,int k)
     7 {
     8      for(int i=x;i<=n;i+=lowbit(i))
     9      {
    10          c[i]+=k;
    11      }
    12 }
    13 int query(int x)
    14 {
    15      int ans=0;
    16      for(int i=x;i>=1;i-=lowbit(i))ans+=c[i];
    17      return ans;
    18 }
    19 int second_divied(int l,int r,int x,int last_rs)
    20 {
    21 
    22     while(l+1<r)
    23     {    
    24          int mid=(l+r)>>1;
    25          if(query(mid)-last_rs<x)
    26          {
    27             l=mid;
    28          }
    29          else r=mid;
    30          //printf("l=%lld r=%lld
    ",l,r);
    31     }
    32     if(query(l)-last_rs==x)return l;
    33     else return r;
    34 }
    35 int find(int pos)
    36 {
    37     if(query(n)-query(pos)==0)
    38     {
    39         return 1ll;
    40     }
    41     return pos;
    42 }int ans=0;
    43 void work2()
    44 {
    45      for(int i=1;i<=n;++i)add(i,1);
    46      int sum=0;int pos=0;int cir=1;//上一位置
    47      while(sum<n-1)
    48      {
    49           int now_rs=query(n);
    50           int last_rs=query(pos);
    51           if(now_rs-last_rs>=cir)
    52           {
    53               pos=second_divied(pos+1,n,cir,last_rs);
    54               add(pos,-1); 
    55               pos=find(pos);       
    56           }
    57           else if(now_rs-last_rs<cir)
    58           {
    59               int t=query(n);
    60               int me=cir;
    61               me=(me-(now_rs-last_rs))%t;
    62               if(me==0)me=t;
    63               pos=second_divied(1,n,me,0);
    64               add(pos,-1);
    65               pos=find(pos);
    66           }
    67           cir++;sum++;
    68      }
    69      ans=second_divied(1,n,1,0);
    70      add(ans,-1);
    71 }
    72 int T=0;
    73 signed main()
    74 {
    75     scanf("%lld",&T);
    76     while(T--)
    77     {
    78          scanf("%lld",&n);
    79              ans=0;
    80              work2();
    81              printf("%lld
    ",ans);
    82     }
    83 }
    View Code

    对于约瑟夫问题

    我们可以知道最后的人一定是升到最后的,他在新的队伍里的编号是零(因为只有一个人,从零开始编号)

    然后我们从后往前递推,考虑最后胜利者在上一层的编号直到最后编号

    我们假设当前层为4,编号为3

    那么在上一层时因为干掉了一个人,那么就从干掉的人的后一个开始编号

    所以上一层是在位置6

    这样我们得到f[i]表示在第i次操作后胜利者所处的编号

    然后就简单了

    #include<bits/stdc++.h>
    #define MAXN 10000001
    using namespace std;
    int T;int n;int ans=0;
    signed main()
    {
        scanf("%d",&T);
        while(T--)
        {
             scanf("%d",&n);
             ans=0;
             for(int i=n-1;i>=1;--i)
             {
                 ans=(ans+i)%(n-i+1);
             }
             printf("%d
    ",ans+1);
        }
    }
  • 相关阅读:
    python高级编程
    django笔记
    sublime ide
    python3 django mysql
    python win
    linux时区设置
    在实际应用中如何实现切圆角的功能
    display和visiblity在应用中使用哪个好
    看懂UML类图和时序图
    解决Xcode7.2真机调试出现:The account “” has no team with ID “”
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11399763.html
Copyright © 2020-2023  润新知