题目描述
给你n张卡片,卡片上仅包含大写英文字母,现你可从这n张卡片中选出k张,要求得到尽可能高的分数。
关于分数的计算方式,在你所选择的k张卡片中,含有相同字母的卡片分数为卡片数乘以相同卡片个数。
就样例而言,选择九张D和其他任意一张,得到的结果为9*9+1 。
输入描述:
输入包含两行,第一行含两个整数n,k(0<k<=n<=1,000,000) 第二行为每张卡片上的字母
输出描述:
输出仅包含一行,输出尽可能高的分数
示例1
输入
15 10 DZFDFZDFDDDDDDF
输出
82
思路
本题标签贪心&排序。
贪心在于从n个当中选出k个卡片,其总分最大,而排序在于k个卡片中重复的个数越多,其分数为每种卡片个数的平方,那么就要将26个字母的个数进行排序,从多的卡片开始选。
代码
#include<iostream>
using namespace std;
int a[1000],b[1000];
long long quicksort(long long a[],int left,int right){
int th=a[left];
while(left<right){
//cout<<a[left]<<","<<a[right]<<endl;
while(left<right&&a[right]>=th)
right--;
a[left]=a[right];
while(left<right&&a[left]<=th)
{left++;}
a[right]=a[left];
}
a[left]=th;
return left;
}
void useQuickSort(long long a[],int left,int right){
if(left>right)
return;
int th=quicksort(a, left, right);
//cout<<"th is "<<th<<endl;
useQuickSort(a, left, th-1);
useQuickSort(a, th+1, right);
}
int main(){
//DZFDFZDFDDDDDDF
//在你所选择的k张卡片中,含有相同字母的卡片分数为卡片数乘以相同卡片个数。
long long n,k,j,sum=0,count=0,i;
string str;
int l=25;
while(cin>>n>>k)
{
cin>>str;
l=25;
sum=0;count=0;
long long a[26]={0};
long long len=str.length();
for(i=0;i<len;i++)
{
a[str[i]-65]++;
}
//快速排序
useQuickSort(a,0,25);
//rest记录还需要的卡片数
long long rest=k-count;
while(rest!=0){
//当数列a中卡片数目小于剩余的卡片,那么直接将数列a中的卡片数抽取,count记录已经抽取的卡片数
if(a[l]<=rest)
{
j=a[l];
count+=a[l];
}
//否则就抽取需要的卡片数
else {count+=rest;j=rest;}
//j记录每次抽取后的卡片数,sum为总的分数
sum+=j*j;
//l为数列a逆序顺序,循环一次后减1
l--;
//计算还需的卡片数
rest=k-count;
}
cout<<sum<<endl;
}//while
return 0;
}
PS
a. 数据被AC70%,问题在于定义长度要为long long
b.在while循环中,每次选择的卡片个数应该用剩余的卡片数和排好顺序的数列逆序比较