题意:让你构造一个只包含小写字母的可重集,每次可以取两个元素,将它们合并,合并的代价是这两个元素各自的从‘a’到‘z’出现的次数之积的和。
给你K,你构造的可重集必须满足将所有元素合而为一以后,所消耗的最小代价恰好为K。
考虑只包含一种类字母的消耗代价,以a为例:
a 0
aa 1
aaa 3
aaa 6
aaaa 10
aaaaa 15
... ...
而且如果再其上任意叠加别的字母的话,是互不干涉的。于是可以贪心地从K中依次减去最大的一个上表中的数,输出那么多‘a’,然后下一次换成'b',如此循环……
容易发现,每一轮会让K变成sqrt(K),所以收敛地非常快。
#include<cstdio> #include<algorithm> using namespace std; int n,base[100005],e; int main(){ int t=0; for(int i=1;;++i){ t+=i; if(t>100000){ break; } base[++e]=t; } scanf("%d",&n); if(n==0){ puts("a"); return 0; } char c='a'; while(n){ int* p=upper_bound(base+1,base+e+1,n); --p; for(int i=1;i<=p-base+1;++i){ putchar(c); } ++c; n-=(*p); } puts(""); return 0; }