第二题我没做出来 :(,但看了几个贴出来的分析结果觉得还不是很满意。

这里我给出精确的用户名和注册码数量,供争议双方参考。这里不考虑超出53位的情况。

注册码的数量:
* 分为三组没问题,efgh, ijkl,abcd ,这三组可以是全排列(本例头3位是3 2 1) , 即p(3,3)=6;
* a, e单独取没问题,所以e,fgh为p(2,2)=2; a,bcd为p(2,2)=2;
* fgh由于程序设计,只能分为f,gh,为p(2,2)=2;
* bcd可以是全排列,p(3,3)=6;
* ijkl可以是全排列,p(4,4)=4;
所以注册码(代表字符)的数量Rs=6*2*2*2*6*4=1152个

用户名的数量:
* 可以在26个字母任意取12个字母组成p(12,26),但其中符合要求的比例为1152/p(12,12)(百万分之一)。所以用户名的数量Us=11125670400个

平均每个注册码大约对应9657700个多个正确的用户名。

这个结果似乎很恐怖,难道算错了?

做一个全覆盖的注册机可以采用如下方法:
* 随机生成12个不同字符的字符串,转换(1-12)后与1152个注册码(代表字符)比较,在其中则输出,不在其中则重新升成。注意成功概率为百万分之一。
* 这里要求有完整的1152个注册码的数据表;

所以100分的注册机工作量太大了,效率也太低。

看了我上面的分析,第二题我0分,大家是不是应该同情我? :)

  • 标 题:答复
  • 作 者:mstwugui
  • 时 间:2008-10-09 17:08

引用:
最初由 nkspark发布 查看帖子
第二题我没做出来 :(,但看了几个贴出来的分析结果觉得还不是很满意。

这里我给出精确的用户名和注册码数量,供争议双方参考。这里不考虑超出53位的情况。

注册码的数量:
* 分为三组没问题,efgh, ijkl,abcd ,这三组可以是全排列(本例头3位是3 2 1) , 即p(3,3)...
我的注册机覆盖的范围比你的计算结果更大一些

关于key的计算我的理解是
根据"ijkl"的触发条件key[4], key[6], key[8], key[10]有4种可能
引用:
                if (temp[key[3]*4+key[4]] == temp[key[5]*4+key[6]])
                {
                    if (temp[key[7]*4+key[8]] == temp[key[9]*4+key[10]])
                        sRet = sRet + 'l';
                    else
                        sRet = sRet + 'k';
                }
                else
                {
                    if (temp[key[7]*4+key[8]] == temp[key[9]*4+key[10]])
                        sRet = sRet + 'j';
                    else
                        sRet = sRet + 'i';
                }
然后根据对临时数组中修正,
key[11],key[14]和key[17]共有6种可能,
123
132
213
231
312
321
key[20],key[23]和key[26]同样也有6种可能,
引用:
                temp[key[1]*4 + key[11]] = temp[key[12]*4+key[13]];
                temp[key[1]*4 + key[14]] = temp[key[15]*4+key[16]];
                temp[key[1]*4 + key[17]] = temp[key[18]*4+key[19]];
                temp[key[2]*4 + key[20]] = temp[key[21]*4+key[22]];
                temp[key[2]*4 + key[23]] = temp[key[24]*4+key[25]];
                temp[key[2]*4 + key[26]] = temp[key[27]*4+key[28]];
最后根据"ae"的触发条件
key[29], key[30], key[31]和key[32]有20种可能
0001
0002
0003
0011
0012
0013
0020
0021
0022
0023
0100
0200
0300
1100
1200
1300
2000
2100
2200
2300
key[45], key[46], key[47]和key[48]同样也有20种可能

引用:
                    if (temp[key[29]*4+key[30]] == temp[key[31]*4+key[32]])
                        sRet = sRet + 'e';
                    else
                        sRet = sRet + 'a';

                    if (temp[key[45]*4+key[46]] == temp[key[47]*4+key[48]])
                        sRet = sRet + 'e';
                    else
                        sRet = sRet + 'a';
因此前53位不重复的key应该有4*6*6*20*20=57600
因为name和key没有一一对应的关系,所以计算起来很简单,我的做法是
先随机生成一个不重复的长度为12,全部由不为z的小写字符组成的字符串,
为了确保大小排序后gh相连,然后再将第8大的字符搬到第7大的字符之后即可,这样就覆盖了用户名的所有可能

  • 标 题:答复
  • 作 者:mstwugui
  • 时 间:2008-10-09 17:24

这里我不再单独计算bcd和fgh是因为根据临时数组的调整判断,这些值应该是固定的
以第一次计算b为例, 数组的值为

引用:
{0x1E, 0x28, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E}
参考如下触发条件
引用:
                    if (temp[key[37]*4+key[38]] > temp[key[39]*4+key[40]])
                        sRet = sRet + 'b';
                    else if (temp[key[37]*4+key[38]] < temp[key[39]*4+key[40]])
                        sRet = sRet + 'c';
                    else if (temp[key[37]*4+key[38]] == temp[key[39]*4+key[40]])
                        sRet = sRet + 'd';
因此key[37],key[38]必须是01

接下来继续第一次计算c, 数组的值为
引用:
 {0x1E, 0x1E, 0x28, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E}
 
 考虑到触发条件因此key[39],key[40]必须是02

因此对于bcd, fgh的控制字节是固定的

  • 标 题:答复
  • 作 者:mstwugui
  • 时 间:2008-10-09 18:17

key[4]和key[6]是可以互换的,但是只有2种可能01或是10
key[8]和key[10]也一样可以互换,同样还是只有两种可能02或是20
你前面计算的1152里面有部分和我的计算是重复的,而且我计算的是控制字节的概率
因此前53位合法key的总数还是57600