• 牛客编程巅峰赛S1第9场


    好久没写过blog了...

    题意:求n的排列中第k个波浪形的排列

    牛客巅峰赛系列里面少有的,还算有一点意思的题目(没错我就是在喷),可惜考场上时间不太够,想出来没码完(好吧确实是因为我一开始把找第k个的部分写麻烦了)。

    首先来考虑求满足条件序列数量的问题,记$dp_{n,k,0/1}$表示长度为n,以k开头的先上升或先下降的序列数量。

    $$ dp_{n,k,0} = sum_{i=1}^{k-1} dp_{n-1,i,1} $$

    $$ dp_{n,k,1} = sum_{i=k+1}^{n} dp_{n-1,i-1,0} $$

    预处理出来这个dp数组之后,按照跟dp相同的思路逐位确定最终答案即可。

    #define ll long long 
    class Solution {
    public:
        /**
         * 
         * @param n int整型 木棒的个数
         * @param k long长整型 第k个排列
         * @return int整型vector
         */
        ll dp[30][30][2];
        vector<int> ask(int n, int now, ll k, int flag){
            vector<int> res, _res;
            if (n>1){
                if (flag == 0){
                    for (int j = 1; j < now; j++){
                        long long tmp = dp[n-1][j][1];
                        if (k > tmp) k-=tmp;else{
                            res = ask(n-1, j, k, 1);
                            break;
                        }
                    }
                }else{
                    for (int j = now+1; j <= n; j++){
                        long long tmp = dp[n-1][j-1][0];
                        if (k > tmp) k-=tmp;else{
                            res = ask(n-1, j-1, k, 0);
                            break;
                        }
                    }
                }
            }
            for (int i = 0; i < n-1; i++) res[i] += res[i] >= now;
            _res.push_back(now);
            for (int i = 0; i < n-1; i++) _res.push_back(res[i]);
            return _res;
        }
        vector<int> stick(int n, ll k) {
            memset(dp, 0, sizeof(dp));
            dp[1][1][0] = dp[1][1][1] = 1;
            for (int i = 2; i <= n; i++){
                for (int j = 1; j <= i; j++){
                    for (int k = 1; k < j; k++){
                        dp[i][j][0] += dp[i-1][k][1];
                    }
                    for (int k = j+1; k <= i; k++){
                        dp[i][j][1] += dp[i-1][k-1][0];
                    }
                }
            }
            for (int a = 1; a <= n; a++){
                if (dp[n][a][0] >= k){
                    return ask(n, a, k, 0);
                }else k-=dp[n][a][0];
                if (dp[n][a][1] >= k){
                    return ask(n, a, k, 1);
                }else k-=dp[n][a][1];
            }
        }
    };
    View Code
  • 相关阅读:
    微信公众号之获取公众平台回复模板,根据关键字动态回复消息 ^
    微信公众号之获取用户信息 ^
    微信公众号之创建自定义菜单.net core 5.0 ^
    微信公众号关注/取消关注回调.net core 5.0 ^
    微信公众号之发送微信模板.net core 5.0 ^
    微信公众号之获取token ^
    Nmap网络扫面工具
    RSA密码算法
    后端返回支付宝HTML,如何使用.H5端调用支付宝支付
    一种把dump里连续的内存保存到文件的方法
  • 原文地址:https://www.cnblogs.com/Enceladus/p/13449605.html
Copyright © 2020-2023  润新知