codeforce 509C (很有趣的贪心模拟构造)

37 篇文章 0 订阅


C. Sums of Digits
time limit per test
2 seconds
memory limit per test
256 megabytes

Vasya had a strictly increasing sequence of positive integersa1, ...,an. Vasya used it to build a new sequenceb1, ...,bn, wherebi is the sum of digits ofai's decimal representation. Then sequenceai got lost and all that remained is sequencebi.

Vasya wonders what the numbers ai could be like. Of all the possible options he likes the one sequence with the minimum possible last numberan. Help Vasya restore the initial sequence.

It is guaranteed that such a sequence always exists.

Input

The first line contains a single integer number n (1 ≤ n ≤ 300).

Next n lines contain integer numbersb1, ...,bn  — the required sums of digits. Allbi belong to the range1 ≤ bi ≤ 300.

Output

Print n integer numbers, one per line — the correct option for numbersai, in order of following in sequence. The sequence should be strictly increasing. The sum of digits of thei-th number should be equal tobi.

If there are multiple sequences with least possible numberan, print any of them. Print the numbers without leading zeroes.

Sample test(s)
Input
3
1
2
3
Output
1
2
3
Input
3
3
2
1
Output
3
11
100

题目大意:给你一组数字每位的和组成的序列,现在要找到原数字组成的序列,该序列是一个严格递增序列, 要求最后一个数字是在所有满足条件的序列中最小的


题目分析:我们根据上一个数字来推出下一个数字,方法是先计算当前位和与前一个位和的差

1.如果差值大于0,直接从上一个数字的最低位开始累加差值,满10进1

2.如果差值小于0,则先从上一个数字的低位依次往后累加差值,直到差值大于0,这里的操作相当于减去上一位数字多出来的部分再进行1操作,举个例子

5
6
10
18
16
7

答案是

6
19
99
169
205

首先 第一个数字肯定不变,接着10,10-6=4>0,因此我们直接从6开始枚举6+3=9因为4-3=1差一位则进位,得到19

18-10=8>0从19的最低位枚举,因为最低位为9,因此从十位枚举,十位是1,加上差值8即十位变成9,得到99

18-16=-2<0 这时要先让差值大于0,在99的最低位9减去2,得到7,将最低位归0,因为第二位也是9,还要进位,进位的时候差值要累加9得到16,十位0,最后我们其实把问题转变为,从100开始找十位和个位和为15的最小数,直接从低位枚举就行了,因为15>9,所以个位就是9,十位是15-9=6,最后得169,一开始得到7时因为97<99,因此我们必须要进位,还有将最低位归0得操作是因为我们要找的是大于前一个数的最小数,因此要从0开始枚举

7-16=-9<0 这时要先让差值大于0,在169最低位9减去9,得到0,将最低位归0,这时候d=0,则加上十位6,十位归0,百位加1,差值减1,转变为从200开始找十位和个位和为5的最小数,枚举得到205.



#include <cstdio>
#include <cstring>
int digit[1000], len = 0;

void next(int d)
{
    for(int i = 1; d > 0; i++) //从低位枚举
    {
        while(d > 0 && digit[i] < 9)
        {
            d--;
            digit[i]++;
        }
        len = i > len ? i : len; //进位的时候要注意更改位数
    }
}

int main()
{
    int n, b[400];
    scanf("%d", &n);
    b[0] = 0;
    for(int i = 1; i <= n; i++)
        scanf("%d", &b[i]);
    for(int i = 1; i <= n; i++)
    {
        int d = b[i] - b[i - 1];
        if(d > 0)
            next(d);
        else 
        {
            for(int i = 1; ; i++)
            {
                len = i > len ? i : len;
                if(d > 0 && digit[i] < 9)
                {
                    d--;
                    digit[i]++;
                    next(d);
                    break;
                }
                d += digit[i];
                digit[i] = 0;
            }
        }
        for(int i = len; i >= 1; i--)
            printf("%d", digit[i]);
        printf("\n");
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值