• Codeforces Round #309 (Div. 2) -D. Kyoya and Permutation


    Kyoya and Permutation

    这题想了好久才写出来,没看题解写出来的感觉真的好爽啊!!!

    题目大意:题意我看了好久才懂,就是给你一个序列,比如[4, 1, 6, 2, 5, 3],第一个数字

    的值是4,那么我们找下标为4的数( 跟链表差不多意思 ),然后一直找到底,这些数分为一类,

    如[4, 1, 6, 2, 5, 3] 就可以分为三类,[4, 2, 1] , [6, 3],[5],这三类,然后每个类里面按从大

    往小排,然后类之间按字典序排,[4, 1, 6, 2, 5, 3] 重新组合之后为,[4, 2, 1] [5] [6, 3]=[4, 2, 1, 5, 6, 3]

    我们把进行重组之后数字序列保持不变的 序列 按字典序大小从小到大排出来。

    然后给你一个长度n和数字k,让你找出长度为n的序列中排第k个的序列是什么。

    思路:首先我想的是怎样的序列它重新组合之后还是原序列,我打了一下表,基础序列为

    1,2,3,4,……,n,只有相邻的两个数交换之后得到的是满足要求的序列。如果我们从小到大

    枚举出所有的序列显然是不可能的复杂度太高,那么我们先求总共的序列数,我们设dp[ i ],

    表示从i 到 n 一共有多少种交换方法。dp[n]=1,那么状态转移方程为dp[ i ] = dp[ i + 1 ]+dp[ i + 2 ] ,

    为什么呢,因为到i这里的时候,我们可以选择交换i 和 i+1 或者不交换,交换的话种数是dp[ i +2 ],

    不交换的话是dp[ i + 1 ]。

    我们从n开始往前找,找到第一个大于k的dp[ s ],那么s和s+1是必须要交换的,因为如果不交换

    种数为dp[ s + 2 ],又dp[ s + 2] < k 不满足。这样我们的问题就变成了k为k-dp[ s + 2]的相同问题

    我们可以用dfs递归求解。

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 ll dp[60],n,k,ans[60],cnt[60];
     5 void dfs(ll k)
     6 {
     7     if(k==1) return;
     8     int item=-1;
     9     for(int i=n;i>=1;i--)
    10     {
    11         if(dp[i]>=k)
    12         {
    13             item=i;
    14             break;
    15         }
    16     }
    17     swap(ans[item],ans[item+1]);
    18     dfs(k-dp[item+1]);
    19 }
    20 int main()
    21 {
    22     cin>>n>>k;
    23     dp[n]=1; dp[n-1]=2;
    24     for(int i=n-2;i>=1;i--) dp[i]=dp[i+1]+dp[i+2];
    25     for(int i=1;i<=n;i++) ans[i]=i;
    26     dfs(k);
    27     printf("%d",ans[1]);
    28     for(int i=2;i<=n;i++) printf(" %d",ans[i]);
    29     puts("");
    30     return 0;
    31 }
    View Code
  • 相关阅读:
    工厂模式简介
    设计模式
    idea的安装与配置及基本用法
    软件架构设计的七大原则
    C#设计模式开启闯关之路
    基础知识详解系列目录
    .Net Core2.2 使用 AutoMapper进行实体转换
    通俗易懂设计模式解析——解释器模式
    通俗易懂设计模式解析——备忘录模式
    通俗易懂设计模式解析——访问者模式
  • 原文地址:https://www.cnblogs.com/CJLHY/p/7551542.html
Copyright © 2020-2023  润新知