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