CSU-ACM2017暑假集训比赛7

来源:互联网 发布:淘宝卖家刷一单10元 编辑:程序博客网 时间:2024/06/05 02:24

F - 凑数字

给定一个n,要求找出一个最短的字符串S,使得所有1到n的整数都是S的子序列。比如n=10,那么S=”1234056789”的时候,是满足条件的。这个时候S的长度是10。现在给出一个n,要求输出最短S的长度。

Input

第1行:给出一个整数n (1<=n<=1e10000)。

Output

输出最短S的长度

Sample Input

10

Sample Output

10

首先一定要明确“子序列”的意义,然后就容易想到,将一个数的位数减一,得到的就是表达除最高位外所有低位数字所需要的字符串“1234567890”的个数。

重要的是最高位如何处理。举一组例子:取四位数 222122222322。首先知道,若不考虑最高位的 2,后三位共需长度为 30 的字符串 str 来表达。现在需要在字符串的首部加入若干字符,从而使得字符串可以表达完整的四位数。

首先考虑 2221:乍一看,会向串首加入字符 ‘2’ 和 ‘1’。但观察后可以发现,只需要在串首添加字符 ‘2’,将字符串长度增至 31 即可完整表达 2221。因为数字 1111 可通过重用 str 中区间为 [1,10] 的字符来表达。

可是,这种规律在数字 2222 上不成立。因为长为 30 的由三个“1234567890”构成字符串只包含三个 ‘1’,我们无法用它来表达数字 1111 。这时,就需要将字符 ‘2’ 和 ‘1’ 同时添加至串首。

再看数字 2322:与 2222 同理,这时也应该将字符 ‘2’ 和 ‘1’ 同时加至串首。

现在可以将上述规律推广到一般情况:
设给定的数字位数为 d, 表达它所需的字符串长度为 len。首先令 len=10×(d1) ,然后从给定数字的最高位出发走向最低位,将途中遇到的第一个与最高位不同的个数字 k 与最高位数字 n 比较,若 k<n,则执行 len=len+n1 操作;若 k>n ,或者找不到任何 kn,则执行 len=len+n 操作。这样得到的字符串 str 拥有足够表达给定数字的最短长度。

#include <string>#include <iostream>#include <algorithm>using namespace std;int main(){#ifdef TESTfreopen("test.txt", "r", stdin);#endif // TEST    string sample;    while(cin >> sample){        int cnt = 0, len = sample.length();        cnt += (len - 1)*10;        cnt += sample[0]-'1';        bool add = true;        for(int i = 1; i < len; i++){            if(sample[i] < sample[i-1]){                add = false;                break;            }            else if(sample[i] > sample[i-1])                break;        }        if(add)            cnt++;        cout << cnt << endl;    }    return 0;}
原创粉丝点击