简单版本和困难版本之间的唯一区别是约束。子序列是一种字符串,它可以通过删除一些符号或不删除符号而不改变剩余符号的顺序来从另一个字符串中导出。
.要删除的字符不需要连续,它们之间可以有任何间隔。例如,对于字符串“abaca”,以下字符串是子序列:“abaca”、“ABA”、“AAA”、“a”和“”(空字符串)。但以下字符串不是子序列:“aabaca”、“CB”和“BCAA”。您将得到一个由 n n n 个小写拉丁字母组成的字符串 s s s 。
在一步中,您可以取给定字符串的任何子序列 t t t ,并将其添加到集合 S S S 中。
集合 S S S 不能包含重复项。此移动花费 n − ∣ t ∣ n - |t| n−∣t∣ ,其中 ∣ t ∣ |t| ∣t∣ 是添加的子序列的长度(即价格等于删除的字符数)。您的任务是找出获得大小为 k k k 的集合 S S S 的最小可能总成本,或者报告不可能做到这一点。
1 ≤ n , k ≤ 100 1 \leq n,k \leq 100 1≤n,k≤100
由于 k ≤ 100 k \leq 100 k≤100,且子序列长度越长约优,将原串加入队列,使用bfs跑出 k k k个子序列即可。
#include
#define ull unsigned long long
#define ll long long
#define inf 0x3f3f3f3f
#define lc p<<1
#define rc p<<1|1
#define endl '\n'
#define all(a) a.begin()+1,a.end()
#define all0(a) a.begin(),a.end()
#define lowbit(a) (a&-a)
#define fi first
#define se second
#define pb push_back
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
using namespace std;
const double eps=1e-6;
typedef pair<int,int>PII;
typedef array<int,3>PIII;
mt19937_64 rnd(time(0));
void solve()
{
int n,k;
cin>>n>>k;
string s;cin>>s;
map<string,int>mp;
ll ans=0;
auto bfs=[&]()
{
queue<string>q;
q.push(s);
mp[s]=1;
while(!q.empty() && k)
{
auto t=q.front();
q.pop();
k--;
int len=t.size();
ans+=n-len;
for(int i=0;i<len;i++)
{
string res=t.substr(0,i)+t.substr(i+1,len-i);
if(!mp[res])
{
mp[res]=1;
q.push(res);
}
}
}
};
bfs();
if(k) cout<<-1<<endl;
else cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
solve();
return 0;
}
1183E的hard版本,区别是 1 ≤ k ≤ 1 0 12 1 \leq k \leq 10^{12} 1≤k≤1012
#include
#define ull unsigned long long
#define ll long long
#define inf 0x3f3f3f3f
#define lc p<<1
#define rc p<<1|1
#define endl '\n'
#define all(a) a.begin()+1,a.end()
#define all0(a) a.begin(),a.end()
#define lowbit(a) (a&-a)
#define fi first
#define se second
#define pb push_back
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
using namespace std;
const double eps=1e-6;
typedef pair<int,int>PII;
typedef array<int,3>PIII;
mt19937_64 rnd(time(0));
void solve()
{
ll n,k;
cin>>n>>k;
string s;cin>>s;
s=" "+s;
vector<vector<ll>>dp(n+1,vector<ll>(n+1));//前j个长度为i的不同子序列
map<char,int>last;
for(int i=0;i<=n;i++) dp[0][i]=1;
for(int i=1;i<=n;i++)
{
for(auto c='a';c<='z';c++) last[c]=0;
for(int j=i;j<=n;j++)
{
dp[i][j]=dp[i-1][j-1]+dp[i][j-1];
if(last[s[j]]) dp[i][j]-=dp[i-1][last[s[j]]-1];
last[s[j]]=j;
}
}
ll sum=0;
ll ans=0;
for(int i=n;i>=0;i--)
{
if(sum+dp[i][n]>k)
{
ans+=(k-sum)*(n-i);
sum=k;
break;
}
sum+=dp[i][n];
ans+=dp[i][n]*(n-i);
}
//cout<
if(sum<k) cout<<-1<<endl;
else cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
solve();
return 0;
}
给定 n n n个数,至多选择三个,且选择的数之间不存在倍数关系,求可以选择的最大和
#include
#define ull unsigned long long
#define ll long long
#define inf 0x3f3f3f3f
#define lc p<<1
#define rc p<<1|1
#define endl '\n'
#define all(a) a.begin()+1,a.end()
#define all0(a) a.begin(),a.end()
#define lowbit(a) (a&-a)
#define fi first
#define se second
#define pb push_back
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
using namespace std;
const double eps=1e-6;
typedef pair<int,int>PII;
typedef array<int,3>PIII;
mt19937_64 rnd(time(0));
void solve()
{
int n;cin>>n;
vector<int>a(n+1);
for(int i=1;i<=n;i++) cin>>a[i];
sort(all(a),greater<int>());
int res1=a[1];
int ans=res1;
int ok2,ok3,ok5;
ok2=ok3=ok5=0;
for(int i=2;i<=n;i++)
{
if(a[i]*2==res1) ok2=1;
if(a[i]*3==res1) ok3=1;
if(a[i]*5==res1) ok5=1;
}
if(ok2 && ok3 && ok5) ans=max(ans,res1/2+res1/3+res1/5);
int res2=0;
for(int i=2;i<=n;i++) if(res1%a[i]) {res2=a[i];break;}
ans=max(ans,res1+res2);
for(int i=2;i<=n;i++)
{
if((res1%a[i]) && (res2%a[i]))
{
ans=max(ans,res1+res2+a[i]);
break;
}
}
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--)
solve();
return 0;
}