CF1332C K-Complete Word(思维)
首先根据数据大小发现肯定是不能暴力的,那么我们开始寻找性质
题目要求每k位循环,并且整个序列要是回文,这就说明了一点,那就是每一个循环节都要是回文数。
所以我们现在转化成了求将整个序列的k位变成同一个回文数的最小代价。
我们发现,就可以用贪心的思想,将数分成k组,每组有若干个,每组中的值都要相等并且第一组和第k组的值要相等,第2和k-1也要相等,这样只需要枚举那个数出现的次数最多就行
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<map> #include<string> using namespace std; typedef long long ll; const int N=2e5+5; const int mod=19260817; int st[N][27]; int main(){ string s; int t; cin>>t; while(t--){ int n,k; cin>>n>>k; cin>>s; s=" "+s; int i; int j; for(i=0;i<=n;i++){ for(j=0;j<26;j++) st[i][j]=0; } for(i=1;i<=n;i++){ int sign=(i-1)%k; sign++; int hh=s[i]-'a'; st[sign][hh]++; } int flag=n/k; if(k%2){ int res=0; for(i=1,j=k;i<j;i++,j--){ int tmp=0; for(int l=0;l<26;l++){ tmp=max(tmp,st[i][l]+st[j][l]); } res+=(flag*2-tmp); } int tmp=0; for(int l=0;l<26;l++){ tmp=max(tmp,st[i][l]); } res+=(flag-tmp); printf("%d\n",res); } else{ int res=0; for(i=1,j=k;i<j;i++,j--){ int tmp=0; for(int l=0;l<26;l++){ tmp=max(tmp,st[i][l]+st[j][l]); } res+=(flag*2-tmp); } printf("%d\n",res); } } return 0; }
没有人不辛苦,只有人不喊疼