洛谷 B3866 [GESP202309 二级] 数字黑洞
第 6 篇 CSDN!
这个题很容易想到能用递归来做…
假设我们有这么一个函数 c n t ( n , a n s ) cnt(n,ans) cnt(n,ans) 表示处理函数 和答案变量 a n s = 0 ans=0 ans=0,那么程序先调用 c n t ( n , 0 ) cnt(n,0) cnt(n,0) (一开始的 a n s = 0 ans=0 ans=0 ),在 c n t cnt cnt 里判断 n n n 是否为 495 495 495,如果是,直接输出 a n s ans ans,然后退出程序。
否则,先让 a n s ans ans 加一,然后再调 c n t ( g − h , a n s ) cnt(g-h,ans) cnt(g−h,ans), g g g 表示重排的最大值, h h h 表示重排的最小值。
那么,
g
g
g 和
h
h
h 该怎么得到?
首先,我们要对
n
n
n 的数位重排,必定会得到
n
n
n 各个数位上的数字,不妨用
a
,
b
,
c
a,b,c
a,b,c 表示他的个位,十位和百位。于是,重排后最大的三位数
g
g
g 为
100
a
+
10
b
+
c
100a+10b+c
100a+10b+c ,最小的三位数
h
h
h 为
100
c
+
10
b
+
a
100c+10b+a
100c+10b+a(假设
a
≥
b
≥
c
a \ge b \ge c
a≥b≥c)
所以,如何得到
a
,
b
,
c
a,b,c
a,b,c 的值呢?
其实,我们有一个通用的规律,即对于一个正整数
n
n
n,其从最低位到最高位的第
k
k
k 位(记为
n
k
n_k
nk)数字为:
n
k
=
⌊
n
1
0
k
−
1
⌋
m
o
d
10
n_k=\lfloor \frac{n}{10^{k-1}}\rfloor\ mod\ 10
nk=⌊10k−1n⌋ mod 10
如 n = 123 , k = 2 n=123,k=2 n=123,k=2 时 n k = ⌊ 123 10 ⌋ m o d 10 n_k=\lfloor \frac{123}{10} \rfloor \ mod\ 10 nk=⌊10123⌋ mod 10,即 12 m o d 10 12\ mod\ 10 12 mod 10,最终结果为 2 2 2
根据这个规律,我们能得到: a = n m o d 10 , b = ⌊ n 10 m o d 10 ⌋ a=n\ mod\ 10,b=\lfloor \frac{n}{10}\ mod\ 10 \rfloor a=n mod 10,b=⌊10n mod 10⌋, c = ⌊ n 100 m o d 10 ⌋ c=\lfloor \frac{n}{100}\ mod\ 10\rfloor c=⌊100n mod 10⌋
那么,如何判断
a
,
b
,
c
a,b,c
a,b,c 哪个最大,哪个第二大,哪个第三大?
在 C++ 中,有一个内置方法
m
a
x
(
x
,
y
)
max(x,y)
max(x,y),能求得
x
x
x 和
y
y
y 中的最大值,也有
m
i
n
(
x
,
y
)
min(x,y)
min(x,y),能求得
x
x
x 和
y
y
y 中的最小值。
于是,我们设
d
d
d 是
a
,
b
,
c
a,b,c
a,b,c 中的最大值,则有:
d
=
m
a
x
(
a
,
m
a
x
(
b
,
c
)
)
d=max(a,max(b,c))
d=max(a,max(b,c))
我们设
e
e
e 是
a
,
b
,
c
a,b,c
a,b,c 中的次小值,则有:
e
=
m
i
n
(
m
a
x
(
a
,
b
)
,
c
)
e=min(max(a,b),c)
e=min(max(a,b),c)
我们设
f
f
f 为
a
,
b
,
c
a,b,c
a,b,c 中的最小值,则有::
f
=
m
i
n
(
m
i
n
(
a
,
b
)
,
c
)
f=min(min(a,b),c)
f=min(min(a,b),c)
那么此时的 g ( 最大值 ) = 100 d + 10 e + f g(\text{最大值})=100d+10e+f g(最大值)=100d+10e+f, h ( 最小值 ) = 100 f + 10 e + d h(\text{最小值})=100f+10e+d h(最小值)=100f+10e+d
所以这次递归的参数
n
n
n 为
g
−
h
g-h
g−h,那么整个题的思路就顺完了!
这个题稍微推导一下还是能 AC 的…
所以,上代码!
#include <bits/stdc++.h>
using namespace std;
int cnt(int n, int ans) {
if (n == 495) {
cout << ans;
exit(0);
}
else {
ans ++;
int a = n % 10, b = n / 10 % 10, c = n / 100 % 10, d = max(a, max(b, c)), e = min(max(a, b), c), f = min(a, min(b, c)), g = d * 100 + e * 10 + f, h = f * 100 + e * 10 + d;
cnt(g - h, ans);
}
}
int main() {
int n, ans = 0;
cin >> n;
cnt(n, ans);
}
总结:
m
i
n
,
m
a
x
min,max
min,max 函数的使用和数位分解