题目大意:
现在你有n个珍珠,每个珍珠的颜色用字母a ~ z来描述。你可以从中选出任意个珍珠以任意顺序串成环,求最多能串成多长的环满足每个珍珠的颜色有k的循环周期。
解法:
枚举答案,对于当前长度用并查集check。
Code:
#include <bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a));
using namespace std;
const int MX = 2e3 + 7;
int n,k;
char s[MX];
int ch[30];
int fa[MX],siz[MX];
bool used[MX];
int find(int x){return fa[x] == x? x : fa[x] = find(fa[x]);}
void unionset(int x,int y){
int f1 = find(x), f2 = find(y);
if(f1 == f2) return ;
if(f1 > f2) swap(f1,f2);
fa[f2] = f1;
siz[f1] += siz[f2];
}
bool judge(int d){
for(int i = 0;i < d;++i) fa[i] = i,used[i] = false,siz[i] = 1;
for(int i = 0;i < d;++i){
unionset(i,(i + k) % d);
}
int a[MX], cnt = 0;
for(int i = 0;i < d;++i){
if(used[find(i)]) continue;
used[find(i)] = true;
a[cnt++] = siz[find(i)];
}
sort(a,a + cnt,greater<int>());
int p = 0;
for(int c = 0;c < 26;++c){
int tot = ch[c];
while(p < cnt){
if(a[p] <= tot) tot -= a[p++];
else break;
}
}
return p == cnt;
}
int solve(){
int res = 1;
clr(ch,0);
for(int i = 1;i <= n;++i){
ch[s[i] - 'a']++;
}
sort(ch,ch + 26,greater<int>());
for(int d = n;d >= 2;--d){
if(d <= ch[0]) {res = d;break;}
if(judge(d)){
res = d;break;
}
}
return res;
}
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&k);
scanf("%s",s+1);
int res = solve();printf("%d\n", res);
}
return 0;
}