• 【NOIP模拟赛】 permutation 数学(打表)


    biubiu~~~

    这道题卡读题卡得很死......首先他告诉我们读循环的时候要顺着圈读,然后又说这个圈在数列上要以最大数开始读,而且以这样的循环的首数排序,得到的序列与原序列一样那么他就是可行序列,所以我们发现任何一个可行序列他的循环一定是连续的一块,因为假设我们有一个循环 x->y->z->a->x,并且假设x最大,那么在数列上只会出现x,y,z,a,那么我们根据循环的定义,他们的原本位置也在这几个里面那么也就是各个循环是一块一块的,然后我们在看刚才的假设,我们发现z是最大的!!!然后发现当且仅当一个循环里是两个数他才是合法的,然后我们归纳一下,一个可行排列里的循环只能是两个相邻的数交换位置,然后我们把这个数列往后排发现是Fibonacci数列,然后就循环一波就好了。

    这道题当然如果你是在是没推出来的话也可以用看脸的打表找规律,但是我还真觉得如果看懂题的话不如推..

    #include <cstdio>
    typedef long long LL;
    namespace Fib{
      LL f[100];
      inline void get(){
        f[0]=f[1]=f[2]=1;
        for(int i=3;i<=50;i++)
          f[i]=f[i-1]+f[i-2];
      }
    }
    namespace Main{
      int n;
      LL k;
      int Ans[55];
      inline void get(){
        scanf("%d%lld",&n,&k);
        int pos=1;
        while(pos<=n){
          LL temp=0;
          int now=0;
          for(int i=0;i<n;i++){
            temp+=Fib::f[i];
            if(temp>=k){
              now=i;
              break;
            }
          }
          if(temp==k){
            if(now==0){
              for(int i=pos;i<=n;i++){
                Ans[i]=i;
              }
              break;
            }
            for(int i=pos;i<=n-now-1;i++)
              Ans[i]=i;
            for(int i=n-now;i+1<=n;i+=2)
              Ans[i+1]=i,Ans[i]=i+1;
            if(Ans[n]==0)Ans[n]=n;
            break;
          }
          k-=temp-Fib::f[now];
          for(int i=pos;i<=n-now-1;i++)
            Ans[i]=i;
          Ans[n-now]=n-now+1;
          Ans[n-now+1]=n-now;
          pos=n-now+2;
        }
      }
    }
    int main(){
      Fib::get();
      Main::get();
      for(int i=1;i<=Main::n;i++)
        printf("%d ",Main::Ans[i]);
      return 0;
    }
  • 相关阅读:
    名信片定做网站
    [置顶] 数据库开发常识
    <IMG>中UserMap的用法
    阿斯钢iojeg9uhweu9erhpu9hyw49
    慎得慌二u赫然共和任务i个屁
    阿斯钢iojeg9uhw8uhy平
    2014校园招聘笔、面经历总结---华为双选会
    PDCA模型的学习
    阿斯钢 弇7人后偶尔一个味5而已
    【HTML】让<pre>标签文本自动换行
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7327599.html
Copyright © 2020-2023  润新知