枚举三位数的密码

密码箱是三位数的密码,也就是一共有1000种情况。

我曾经用枚举法找回忘记的密码,试了900多个才成功,大约10分钟。

今天在机房看到主机都是用密码锁锁起来的,仔细思考了一番,发现这里面蕴含着一些规律。

 

最普通的枚举法,自然是从000到999枚举了。

这种枚举法有2个规律

规律一:百位、十位、个位每次最多只变化1(从9到0也算变化1)

比如说,从9到10,百位不变,十位变化1,个位变化1

规律二:个位每次都变,即变化了999次,十位变化99次,百位只变化9次,一共是1107次

 

有没有变化更少的方案呢?

我想到了2048的策略,同样的,枚举密码也可以采用这种来回绕的方法

0 1 2 3 4 5 6 7 8 9 19 18 17 16 15 14 13 12 11 10 

20 21 22 23 24 25 26 27 28 29 39 38 37 36 35 34 33 32 31 30 

40 41 42 43 44 45 46 47 48 49 59 58 57 56 55 54 53 52 51 50 

60 61 62 63 64 65 66 67 68 69 79 78 77 76 75 74 73 72 71 70 

80 81 82 83 84 85 86 87 88 89 99 98 97 96 95 94 93 92 91 90

可以发现,对于这种枚举法,对于前面这些数来说,

每次都只有1位变化了1,另外2位不变。

 

如果后面是从100到190,200到290......900到990,这样的话,

只有在百位发生变化的时候才会有2位发生了变化。

所以,一共是发生了1008次变化。

计算变化次数的代码:

 

#include<iostream>
#include<iomanip>
using namespace std;

int f(int a, int b)
{
	return (a % 10 != b % 10) + (a / 10 % 10 != b / 10 % 10) + (a / 100 != b / 100);
}

int map(int n)
{
	if (n / 10 % 2 == 0)return n;
	int s = n % 10;
	return n - s + 9 - s;
}

int main()
{
	int s = 0;
	for (int i = 0; i < 999; i++)
	{
		cout << setw(4) << map(i);
		s += f(map(i), map(i + 1));
	}
	cout << endl << s;
	return 0;
}

这里的map就是一个计算数列通项的函数

结果果然也是1008

 

不过这还不是最好的结果。

最好的结果,是根据百位再度来回绕。

代码也很好改,只需要用复合函数就可以了

代码:

 

#include<iostream>
#include<iomanip>
using namespace std;

int f(int a, int b)
{
	return (a % 10 != b % 10) + (a / 10 % 10 != b / 10 % 10) + (a / 100 != b / 100);
}

int map(int n)
{
	if (n / 10 % 2 == 0)return n;
	int s = n % 10;
	return n - s + 9 - s;
}

int map2(int n)
{
	if (n / 100 % 2 == 0)return map(n);
	int s = n % 100;
	return map(n - s + 99 - s);
}

int main()
{
	int s = 0;
	for (int i = 0; i < 999; i++)
	{
		cout << setw(4) << map2(i);
		s += f(map2(i), map2(i + 1));
	}
	cout << endl << s;
	return 0;
}

而且很有意思的是,map2和map差不多

 

运行结果:

很明显,这个就是变化最少的方案了,每2个数之间,都只有一位发生了变化。

 

当然,如果手动枚举密码的话,还是最普通的比较靠谱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值