zoukankan      html  css  js  c++  java
  • AISing Programming Contest 2021(AtCoder Beginner Contest 202)D题题解

    D - aab aba baa

    题面

    Among the strings of length (A + B) containing (A) occurrences of a and (B) occurrences of b, find the string that comes (K)-th in the lexicographical order.

    题面意思是给定(A)a(B)b所组成的字符串,问若按字典序排列这个字符串,则按照从小到大第(K)个字典序的字符串表示是什么。

    样例解释:

    2 2 4
    

    两个a和两个b组成的字符串的字典序从小到大为: aabb, abab, abba, baab, baba, bbaa
    第四个为baab,即答案为baab

    解题思路

    只有'a','b'两个字母,且跟排列有关,于是想试试他的K值是否与组合数有关。

    最后找到了如下关系:

    (根据高中数学 (C_{a+b}^{a})的值即为所有组合情况)

    cur表示能构造出前cur个字典序,初始化为0(现在不能理解没有关系)
    设输入的a为剩余a的数量
    设输入的b为剩余b的数量
    设输入的k为第k个字典序字符串

    现在假设按样例输入

    2 2 4
    

    一共四位值,则假设第一位值是a,
    那么现在所有的组合数为 (C_{a+b-1}^{a-1})

    (d=C_{a+b-1}^{a-1})

    则 d + cur 为能覆盖到的字典序(d+cur及之前的字典序都能实现)

    (d + cur >= k) 则说明第一位为a的情况下,a这个位置满足条件,后面可以继续构造)
    否则说明当前位不能为a,则输b然后cur += d。

    代码如下

    #include <iostream>
    
    using namespace std;
    
    typedef long long ll;
    const int N = 100;
    
    ll q[N][N];
    
    
    /* 求组合数 */
    void solve ( void )
    {
        for ( int i = 0; i < N; i++ )
        {
            for ( int j = 0; j <= i; j++ )
            {
                if ( !j )
                {
                    q[i][j] = 1;
                    continue;
                }
    
                q[i][j] = q[i - 1][j] + q[i - 1][j - 1];
            }
        }
    }
    
    ll C ( ll a, ll b )
    {
        return q[a][b];
    }
    
    int main ( void )
    {
        solve();	/* 预处理组合数 */
    
        ll a, b, k;
        cin >> a >> b >> k;
    
        for ( ll m = a + b, i = 0, cur = 0; i < m; i++ )
        {
            ll d = C( a + b - 1, a - 1 );
    
            if ( a == 0 ) cout << 'b';
            else if ( b == 0 ) cout << 'a';
            else if ( k <= cur + d ) cout << 'a', a--;
            else cout << 'b', b--, cur = min ( k, cur + d );
        }
    
        return 0;
    }
    
    作者:Jude_Zhang
    关于博主:评论和私信会在第一时间回复。或者直接私信我。
    版权声明:本博客所有文章除特别声明外,均采用BY-NC-SA 许可协议。转载请注明出处!
    支持博主:如果您觉得文章对您有帮助,可以点击文章下方赞一下。您的鼓励是博主的最大动力!
  • 相关阅读:
    django添加检查用户名和手机号数量接口
    1.vue发送短信逻辑
    Celery 配置与基本使用 并且用celery 一步发送短信
    递归基础_并查集思想_二叉树最大深度问题
    递归基础_汉诺塔问题_经典的多状态问题_整体法/分两个函数互相递归
    递归基础_全排列+改写_组合数
    递归基础_组合数_输出的各种办法(递归)_(持续更新)
    关于gpu版本的tensorflow+anaconda的一些安装问题(持续更新)
    吴恩达课程笔记_1-1~1-4
    bfs和dfs辨析—基础复习(从stack和queue的角度来理解区别,加深理解,不再模糊)
  • 原文地址:https://www.cnblogs.com/judezhang/p/14810546.html
Copyright © 2011-2022 走看看