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;
}
View Code

 

posted @ 2020-04-13 23:03  朝暮不思  阅读(292)  评论(0编辑  收藏  举报