AISing Programming Contest 2021(AtCoder Beginner Contest 202)(补题)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AISing Programming Contest 2021(AtCoder Beginner Contest 202)(补题)相关的知识,希望对你有一定的参考价值。

D - aab aba baa

在这里插入图片描述在这里插入图片描述
题意: 就是给你A个‘a’和B个‘b’,由a和b组成的所有字符串按字典序排列,输出第k个字符串。
思路:和全排列有关,对于所有的排列情况,就是C(a+b,a).假设n=A+B.
假设第一个字母你确定为‘a’那么你看剩下A-1个‘a’和B个‘b’的组合情况。
如果小于K,说明你选‘a’是不合法的。不合法的原因是,C(n-1,a-1)这个数比k还小,说明现在以a开头的字符串在字典序的顺序中已经在第k个之前了,只能选‘b’了。来使字符串在字典序中的顺序靠后。
如果大于等于K, 说明选‘a’是合法的.合法的原因是,C(n-1,a-1)这个数比k还大,说明现在以a开头的字符串在字典序的顺序中已经在第k个之后了(或者等于),可以靠后面的字符串的组合来使字符串在字典序中的位置处在第K位置。
所以,需要预处理出来组合数来,组合数的处理需要用 C ( i , j ) = C ( i − 1 , j ) + C ( i − 1 , j − 1 ) C(i,j)=C(i-1,j)+C(i-1,j-1) C(i,j)=C(i1,j)+C(i1,j1)
当j等于0时, C ( i , 0 ) = 1 C(i,0)=1 C(i,0)=1
来求出所有的组合数情况,然后在利用上面的假设,从前往后对每个位置都进行判断选‘a’还是选‘b’,选‘b’的时候,K要减去当前位置选‘a’的所有情况数(这些都是无效情况了,要减去),当只剩下a或者b的时候就直接输出对应的字母。
下面附上代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e6+10;
#define ll long long
ll dp[63][63];
int a,b;
ll k;
void pre() {
    for(int i=0;i<=61;i++) {
        dp[i][0]=1;
    }
    for(int i=1;i<=60;i++) {
        for(int j=1;j<=i;j++) {
            dp[i][j]=dp[i-1][j]+dp[i-1][j-1];
        }
    }
}
int main() {
    pre();
    cin>>a>>b>>k;
    int n=a+b;
    for(int i=1;i<=n;i++) {
        if(a==0) {
            while(b) {
                cout<<'b';
                b--;
            }
            return 0;
        }
        if(b==0) {
            while(a) {
                cout<<'a';
                a--;
            }
            return 0;
        }
        if(k<=dp[n-i][a-1]) {
            a--;
            cout<<"a";
        }
        else {
            b--;
            cout<<"b";
            k-=dp[n-i][a-1];
        }
    }
    return 0;
}

E题涉及启发式合并,暂时没学,学完这个算法后再来补
F涉及凸包算法
现在会的算法还太少,最后两个题设计的算法,还不太会,先学再补。
To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

以上是关于AISing Programming Contest 2021(AtCoder Beginner Contest 202)(补题)的主要内容,如果未能解决你的问题,请参考以下文章