洛谷 B3866 [GESP202309 二级] 数字黑洞: 思路 和 C++ 题解

洛谷 B3866 [GESP202309 二级] 数字黑洞

第 6 篇 CSDN!

洛谷 B3866 [GESP202309 二级] 数字黑洞

这个题很容易想到能用递归来做…

假设我们有这么一个函数 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(gh,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 abc

所以,如何得到 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=10k1n 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 gh,那么整个题的思路就顺完了!
这个题稍微推导一下还是能 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 函数的使用和数位分解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值