找数字

找数字

给定一个正整数 $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/

posted @ 2023-02-12 10:16  onlyblues  阅读(50)  评论(0编辑  收藏  举报
Web Analytics