zoukankan      html  css  js  c++  java
  • The Preliminary Contest for ICPC Asia Shanghai 2019 F. Rhyme scheme(dp)

     

     题意:给你一个n和k 要你找到长度为n 字典序第k小的字符串 定义一个字符串合法:第i的字符的范围只能是前i-1个字符中的最大值+1

    思路:我们dp[n][i][j]表示长度为n 在第i位 最大值为j的序列有多少个 随后我们可以直接模仿找第k大一样找到第k个字符串

    #include <bits/stdc++.h>
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const double eps = 1e-6;
    const int N = 1e6+7;
    typedef long long ll;
    typedef __int128 bll;
    const ll mod = 998244353;
    using namespace std;
    inline __int128 read() {
         __int128 x=0,f=1;
         char ch=getchar();
         while(ch<'0'||ch>'9') {
             if(ch=='-')
                 f=-1;
             ch=getchar();
         }
         while(ch>='0'&&ch<='9') {
             x=x*10+ch-'0';
             ch=getchar();
         }
         return x*f;
    }
    inline void print(__int128 x)
    {    
       if(x<0){putchar('-');x=-x;}
       if(x>9) print(x/10);
       putchar(x%10+'0');
    }
    bll dp[30][30][30];
    char v[30];
    bll dfs(int len,int now,int mx){
        if(now==len){
            dp[len][now][mx]=1;
            return dp[len][now][mx];
        }
        if(dp[len][now][mx]!=-1) return dp[len][now][mx];
        bll ans=0;
        for(int i=1;i<=min(mx+1,26);i++){
            if(i<=mx){
                ans+=dfs(len,now+1,mx);
            }else{
                ans+=dfs(len,now+1,i);
            }
        }
        dp[len][now][mx]=ans;
        return ans;
    }
    int main(){
    //    ios::sync_with_stdio(false);
    //    cin.tie(0); cout.tie(0);
        int t; scanf("%d",&t);
        for(int i=0;i<30;i++)
            for(int j=0;j<30;j++)
                for(int k=0;k<30;k++)
                    dp[i][j][k]=-1;
        for(int i=1;i<=26;i++)
            dfs(i,1,1);
        int w=0;
    //    print(dp[3][1][1]);
        while(t--){
            int n; scanf("%d",&n);
            bll k; k=read();
            int mx=1;
            printf("Case #%d: ",++w);
            for(int i=1;i<=n;i++){
                v[i]='A'; 
                for(int j=1;j<=mx+1;j++){
                    //cout<<k<<" "<<dp[n][i][j]<<endl;
                    int p=max(mx,j);
                    if(dp[n][i][p]>=k){
                    //    mx=max(mx,j);
                        v[i]=char(j+'A'-1);
                        //putchar('A' + j - 1);
                        mx=max(mx,p);
                    //    cout<<j<<endl;
                        break;
                    }else{
                        k-=dp[n][i][p];
                    }
                }
            }
            for(int i=1;i<=n;i++)
                printf("%c",v[i]);
            puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    高精度计算模板
    P1108 低价购买 [DP][统计方案]
    POJ3349 Snowflake Snow Snowflakes [哈希]
    P1312 Mayan游戏 [深搜][模拟]
    P1378 油滴扩展[深搜]
    P1514 引水入城[搜索,线段覆盖]
    TYVJ1391 走廊泼水节
    【BZOJ1196】公路修建问题
    【BZOJ3624】免费道路
    【BZOJ2429】聪明的猴子
  • 原文地址:https://www.cnblogs.com/wmj6/p/11564257.html
Copyright © 2011-2022 走看看