传送门
- 题意:给出一个n个数的数组(b)。数组(b)中的n个数据表示n个数据(n个数据存储于数组a)的十进制表示下的数字之和,并且数组a严格单调递增,数组a的最后一个数据
a[n]
最小。请求出满足以上条件的序列a。 - 思路:贪心。要使最后一位最小,只要让数组a中的每一位数字尽量小即可。
- 贪心思路:
d = b[i] - b[i - 1]
。若d > 0,则只需要让最低位尽可能地取9,余下的作为最高位。若d <= 0,则可以从最低位开始,让d 加上最低位,直到d > 0(从最低位第1位开始,假设d > 0时位于第j位),则让j + 1 位加 1,让不大于j的数位等0。若此时j + 1位为9,则继续将大于数位j的数字加到d上,直到该数位不等于9(假设为第j位),然后让j + 1位加 1即可。
(以上过程可能不太好理解)
举个例子:b1 = 30, b2 = 23. d = b2 - b1 = -7
a1 = 3999(第三个9是第一位,也即最低位), d + 9 = 2 > 0,第一位赋值0,即3990,由于第二位和第三位都是9,无法进位(也不是无法进位,只是进位后等于0,等于就意味着d得同时加上9),所以,对3进位,即4000,此时d = 2 + 9 + 9 = 20,然后问题就转化为十进制表示下每一位数的和等于20的最小表示。
#include<cstdio>
#include<queue>
#include<set>
#include<cstdlib>
#include<string.h>
#include<string>
#include<iostream>
#include<cmath>
#include<map>
#include<algorithm>
#define endl "\n"
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
#define ft first
#define sd second
#define pll pair<ll, ll>
#define pii pair<int, int>
#define ll long long int
#define mt(a,b) memset(a, b, sizeof a)
const int inf = 0x3f3f3f3f;
const int INF = 0x7fffffff;
using namespace std;
const int N = 2e5 + 7, M = 1e6;
int b[400];
int num[400];
int net(int d, int len)
{
int i = 1;
while (d > 0)
{
while (num[i] == 9) i++;
num[i]++, d--;
}
return max(len, i);
}
int main()
{
IOS;
int n; cin >> n;
for (int i = 1; i <= n; i++) cin >> b[i];
int len = 0;
for (int i = 1; i <= n; i++)
{
int d = b[i] - b[i - 1];
if (d > 0) len = net(d, len);
else
{
int j = 1;
while (d <= 0 || num[j] == 9)
{
d += num[j];
num[j++] = 0;
}
num[j]++; d--;
len = max(j, len);
len = net(d, len);
}
for (int j = len; j >= 1; j--)
cout << num[j];
cout << endl;
}
return 0;
}
大佬链接