Codeforcecs1183H Subsequence(hard version) 求字符串本质不同子序列个数

Posted qingjiuling

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforcecs1183H Subsequence(hard version) 求字符串本质不同子序列个数相关的知识,希望对你有一定的参考价值。

题目链接:https://www.luogu.org/problem/CF1183H

题意:给你一个长为n(100)的字符串,你需要找出k(1e12)个它本质不同的子序列,且没找出一个子序列的花费为n-len(子序列),求最小花费

分析:很明显想让花费最小,就从长度最大的子序列开始找,就转化成找每个长度的本质不同的子序列有多少个

我们用dp[i][j]表示从第i个字符开始,长度为j的子序列个数有多少个。

直接转移的话会出现重复,比如baa,你就会找出两个ba

所以对于每一个i,我们用一个vis数组标记,只转移相同字符第一个出现的那一个

为了保证序列是一个个加的,我们dp的第一维是长度Len

之后贪心寻找答案即可

注意:因为空串也是一个子序列,初始化的时候i=0的也要考虑,并且之后每个非空序列其实都相当于包含了一个空串,循环dp求解的时候也从i=0开始,最后寻找答案的时候就直接从dp[0][len]到dp[0][1]了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int maxn=2e5+7;
const int N=1e4;
char s[110];
ll dp[210][210];
int vis[100];
int main()
    int n;ll k;cin>>n>>k;
    k--;//第一个选的全串没有花费 
    scanf("%s",s+1);
    for(int i=0;i<=n;i++)dp[i][1]=1;
    for(int len=2;len<=n;len++)
        for(int i=0;i<=n;i++)
            memset(vis,0,sizeof(vis));
            for(int k=i+1;k<=n;k++)
                if(!vis[s[k]-a])
                    vis[s[k]-a]=1;
                    dp[i][len]+=dp[k][len-1];
                
            
        
    
    ll ans=0;
    //cout<<dp[0][4]<<" 233\n";
    for(int len=n;len>0&&k!=0;len--)
        if(dp[0][len]<=k)
            k-=dp[0][len];
            ans+=1ll*(n+1-len)*dp[0][len];
        
        else
            ans+=1ll*(n+1-len)*k;
            k=0;
        
    
    if(k>0)printf("-1\n");
    else printf("%I64d\n",ans);
    return 0;

 

以上是关于Codeforcecs1183H Subsequence(hard version) 求字符串本质不同子序列个数的主要内容,如果未能解决你的问题,请参考以下文章

[CF1183H] Subsequences (hard version) - dp

[CF1183H] Subsequences (hard version) - dp

Codeforcecs 459D Pashmak and Parmida's problem 树状数组 OR 分治

Codeforces工具总结