Codeforces Round #431 (Div. 2) ——C. From Y to Y(思路)

From beginning till end, this message has been waiting to be conveyed.

For a given unordered multiset of n lowercase English letters ("multi" means that a letter may appear more than once), we treat all letters as strings of length 1, and repeat the following operation n - 1 times:

  • Remove any two elements s and t from the set, and add their concatenation s + t to the set.

The cost of such operation is defined to be , where f(s, c) denotes the number of times character cappears in string s.

Given a non-negative integer k, construct any valid non-empty set of no more than 100 000 letters, such that the minimum accumulative cost of the whole process is exactly k. It can be shown that a solution always exists.

Input

The first and only line of input contains a non-negative integer k (0 ≤ k ≤ 100 000) — the required minimum cost.

Output

Output a non-empty string of no more than 100 000 lowercase English letters — any multiset satisfying the requirements, concatenated to be a string.

Note that the printed string doesn't need to be the final concatenated string. It only needs to represent an unordered multiset of letters.

Examples
input
Copy
12
output
abababab
input
Copy
3
output
codeforces
Note

For the multiset {'a''b''a''b''a''b''a''b'}, one of the ways to complete the process is as follows:

  • {"ab""a""b""a""b""a""b"}, with a cost of 0;
  • {"aba""b""a""b""a""b"}, with a cost of 1;
  • {"abab""a""b""a""b"}, with a cost of 1;
  • {"abab""ab""a""b"}, with a cost of 0;
  • {"abab""aba""b"}, with a cost of 1;
  • {"abab""abab"}, with a cost of 1;
  • {"abababab"}, with a cost of 8.

The total cost is 12, and it can be proved to be the minimum cost of the process.


题意:

想要得到一个,由'a'-'z'构成的价值为k的字符串。

先是将串拆分成长度为一的子串,然后每次合并两个子串,s1,s2,价值为,s1中每种字母出现次数 * s2中与其相同字母出现次数 之和。

大概就这意思,结合样例理解下。


思路:

计算每个长度为1的子串的贡献值。

从前向后遍历,每位的贡献值,就是这个字母,在其后出现次数。

某个字母出现n+1次,这种字母贡献值为 (1+2+3+……+n) ,即 ((n*(n-1))/2

每种字母的贡献值之和为k,即可。


那么 预处理下前500位n的贡献值,二分,分解k即可。


代码:

至少由一个字母,这里wa了一发 %%%

#include<stdio.h>
#include<algorithm>
using namespace std;

#define For(a,b,c) for(int a = b; a <= c; a++)

int v[505];

int main()
{
    For(i,1,500) v[i] = i*(i-1)/2;
    int k, tot = 0, j;
    scanf("%d",&k);

    while(k)
    {
        int j = upper_bound(v,v+501,k) - v - 1;
        k -= v[j];
        while(j--) printf("%c",'a'+tot);
        tot++;
    }
    printf("%c\n",'a'+tot);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值