找数字
找数字
给定一个正整数 $m$ 和一个非负整数 $s$。
请你找到长度为 $m$ 且各位数字之和为 $s$ 的最小和最大非负整数。
要求所求非负整数不得包含前导零。
输入格式
共一行,两个整数 $m,s$。
输出格式
在一行内输出满足条件的最小和最大非负整数。
如果无解,则输出 -1 -1。
数据范围
前 $6$ 个测试点满足 $1 \leq m \leq 3$。
所有测试点满足 $1 \leq m \leq 100$,$0 \leq s \leq 900$。
输入样例1:
2 15
输出样例1:
69 96
输入样例2:
3 0
输出样例2:
-1 -1
解题思路
先考虑没有解的情况。由于有$m$位数字,每一位最大是$9$,因此$s$要满足$s \leq 9m$,否则无解。同时由于非负整数不能含有前导零,因此如果$m > 1$那么$s$要满足$s > 1$,否则如果$s = 0$,那么$m$只能为$1$,这个时候最大值和最小值均取$0$。
因此无解的情况就是$s > 9m$或者$s = 0 \ \mathrm{\&\&} \ m > 1$。
先看一下怎么求最大值。从高位往低位考虑,对于每一位肯定是能填多大就填多大,因为如果某一位可以填$9$,那么无论怎么样都一定比填$8$得到的结果要大。如果当前剩下位的数字之和为$s$,那么这一位能填的最大数字就是$\min \{ {9, s} \}$。
然后是最小值。可以从低位往高位考虑,如果想让结果最小那么最后一位越大越好。比如如果最后一位可以填$9$,如果此时填$8$的话,那么前面位的数字之和会比填$9$的要多$1$。而由于相对于填$8$的情况,填$9$的话可以给前面某一位减$1$,因此填$9$得到的结果必然比填$8$得到的结果小。如果当前位不是最高位,那么这一位最大可以填的数字是$\min \{ {9, s-1} \}$,减$1$是因为最高位至少要填$1$。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() { 5 int n, m; 6 cin >> n >> m; 7 if (m > 9 * n || !m && n > 1) { // 无解的情况 8 cout << "-1 -1"; 9 return 0; 10 } 11 string a(n, 0), b(n, 0); 12 int s = m; 13 for (int i = n - 1; i; i--) { // 从低位往高位构造最小值 14 int t = min(9, s - 1); // 减1是因为最高位至少是1 15 a[i] = t + '0'; 16 s -= t; 17 } 18 a[0] = s + '0'; // 最高位填的数 19 s = m; 20 for (int i = 0; i < n; i++) { // 从高位往低位构造最大值 21 int t = min(9, s); 22 b[i] = t + '0'; 23 s -= t; 24 } 25 cout << a << ' ' << b; 26 27 return 0; 28 }
参考资料
AcWing 4807. 找数字(AcWing杯 - 周赛):https://www.acwing.com/video/4619/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17113346.html