题目链接:https://codeforc.es/contest/1070/problem/J
题意:给出一个长度为 k 的字符串,选出 n 个和 m 个不同位置的字符构成两个字符串,使得两个字符串相同字母的对数最少。
题解:在最优解的情况下,两个字符串相同的字母只有一个(假设有两种相同的字母,调换他们的位置变得只有一种相同字母的时候更优,可以自行草稿纸上写下不等式证明),可以枚举相同的字母,剩下的字母做 01 背包判断可以构成的最大长度即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define mp(a,b) make_pair(a,b)
#define pi acos(-1)
#define pii pair<int,int>
#define pb push_back
const int INF = 0x3f3f3f3f;
const double eps = 1e-;
const int MAXN = 2e5 + ;
const int MAXM = 1e3 + ;
const ll mod = 1e9 + ; char s[MAXN];
int cnt[], dp[MAXN]; int main() {
#ifdef local
freopen("data.txt", "r", stdin);
#endif
int t;
scanf("%d",&t);
while(t--) {
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
scanf("%s",s + );
mst(cnt, );
for(int i = ; i <= k; i++) cnt[s[i] - 'A' + ]++;
ll ans = 1ll * n * m;
for(int i = ; i <= ; i++) {
for(int j = ; j <= k; j++) dp[j] = ;
dp[] = ;
for(int j = ; j <= ; j++) {
if(i == j) continue;
for(int h = k; h >= cnt[j]; h--) dp[h] |= dp[h - cnt[j]];
}
for(int j = ; j <= k; j++) {
if(!dp[j]) continue;
int x = max(, n - j), y = max(, m - (k - cnt[i] - j));
if(x + y <= cnt[i]) ans = min(ans, 1ll * x * y);
}
}
printf("%lld\n",ans);
}
return ;
}