Project1

标题: 蛋疼数学程序帝!散列算法 [打印本页]

作者: 紫苏    时间: 2010-8-27 11:11
标题: 蛋疼数学程序帝!散列算法
继 chaochao 之后(http://rpg.blue/forum.php?mod=viewthread&tid=140141)的第二波蛋疼,欢迎各位踊跃参加,参与就有奖励!这次的主题是散列函数!

散列结构是一种十分高效的数据结构,在设计良好的散列函数驱动下,散列结构的各种基本操作都只需要平摊的常量时间内完成。散列元素由其唯一的散列码标识,散列码相同的元素被视为相等元素,不可同时存在于结构中。我们这次的任务就是设计一个计算散列码的散列函数

给你一个包含了两个整数域 x、y 的 Point 结构(设 Point 结构集合为 P),找到一个计算完美散列码(Z 中的一个元素)的散列函数 F:P->Z,使得 F(a) = F(b) 当且仅当 a.x = b.x AND a.y = b.y
所谓完美,是指永远不会出现散列碰撞,即出现两个不同的点(x 不相等或 y 不相等)却生成了相同散列码的情况。该散列函数必须一次性生成无冲突散列码
(注:这里的 = 关系是整数集合 Z 中的 =,相等关系)

Ruby 程序框架:

  1. class S
  2.   def initialize(a, b)
  3.     @a, @b = a, b
  4.   end
  5.   def eql?(obj)
  6.     return self.hash == obj.hash
  7.   end
  8.   def hash
  9.     #...
  10.   end
  11. end
复制代码
这里的 hash 方法就是 Point 类的散列函数(方法),我们的目的就是要实现 hash 方法,使得 x 和 y 都相同的 Point 对象在 Ruby 的散列表中被视为相同的键,而不会重复生成元素
演示——
覆盖继承自 Object 的 hash 方法前:

  1. ret = {}
  2. ret[Point.new(1, 0)] = 1
  3. ret[Point.new(2, 3)] = 2
  4. ret[Point.new(1, 0)] = 3
  5. ret[Point.new(1, 0)] = 4
  6. p ret[Point.new(1, 0)]  # => nil
  7. p ret                   # => 四个点的对象都存在与散列表中,但其实第1、3、4个点是相同的
复制代码
完美实现 hash 方法后:

  1. ret = {}
  2. ret[Point.new(1, 0)] = 1
  3. ret[Point.new(2, 3)] = 2
  4. ret[Point.new(1, 0)] = 3
  5. ret[Point.new(1, 0)] = 4
  6. p ret[Point.new(1, 0)]  # => 4
  7. p ret                   # => 只包含两个不同的点 (1,0) 和 (2, 3)
复制代码
为了方便在 Ruby 中测试,你可以做如下假设:x 和 y 的值在 15 位整数的表示范围内,即 -16384 到 +16383,这样生成的散列码就是一个 30 位整数,能够被 Fixnum 表示

要求:给出能说明算法的伪代码,或者详细代码
语言不限,重在参与,欢迎提问和讨论
作者: 忍也忍    时间: 2010-8-27 11:15
完全看不懂的表示很有压力。
作者: 八云紫    时间: 2010-8-27 11:21
就是说给定一组 (x, y) ,在 x y 都相等的情况下,值才相等,对么??
作者: 小幽的马甲    时间: 2010-8-27 11:22
一向是以模一个大质数为Hash值,碰撞时做成一个链表
完美哈希还真没想过……
作者: 八云紫    时间: 2010-8-27 11:41
本帖最后由 月兔铃仙 于 2010-8-27 11:55 编辑
  1. #include "md5.h"
  2. #include <iostream>

  3. using namespace std;

  4. void PrintMD5(const char* &str, MD5& md5) {
  5.   cout << "MD5(\"" << str << "\") = " << md5.toString() << endl;
  6. }

  7. int main(int argc, char* argv[]) {

  8.         MD5 md5;
  9.         md5.update("12");
  10.         PrintMD5("", md5);

  11.         md5.update("21");
  12.         PrintMD5("21", md5);

  13.         return 0;
  14.        
  15. }
复制代码
按照 MD5 的定义应该可以,只是可能结果的长度太长了点~~~

-------------------------

Wndows 下无编译器,测试不能,Linux 下不会输出,悲剧~~~~
作者: DeathKing    时间: 2010-8-27 11:58
本帖最后由 DeathKing 于 2010-8-27 12:07 编辑

看得不是很明白,说的不知道是不是这个意思:

1、映射GET_HASH:P->Z是一个1对1的函数
2、对于e∈P,GET_HASH(e)是e的唯一标识符?(也就是唯一的全局识别id?)

也就是Point.new(1,0)就像1、2那样,是个固定数,也不像Float那样,每次生成的虽然值一样,但是对象却不一样?
作者: 雷欧纳德    时间: 2010-8-27 12:00
实际只要重载Point的等于、小于比较符就能直接用Point对象做key值完成了吧
作者: 小幽的马甲    时间: 2010-8-27 12:02
本帖最后由 小幽的马甲 于 2010-8-27 12:47 编辑
  1. hash = (@a << 14) + @b
  2. return hash
复制代码
= =这样行么……
-------------------------------------------
忘记有符号了……

  1.     aa = @a >= 0 ? 1 : 0
  2.     bb = @b >= 0 ? 1 : 0
  3.     @a = (aa << 14) | @a.abs
  4.     @b = @b.abs
  5.     hash = (@a << 14) + @b
  6.     hash = - hash if aa ^ bb == 1
  7.     return hash
复制代码
= =
作者: DeathKing    时间: 2010-8-27 12:06
本帖最后由 DeathKing 于 2010-8-27 13:17 编辑
  1. class Point
  2.   def hash
  3.     return "#{@x}.#{@y.to_s.resive}".to_f
  4.   end
  5. end
复制代码
hash只能接受Integer(Fixnum)么{:nm_3:}
正在考虑返回Fixnum的方法。

[line]1[/line]

好吧,仔细看看这道题并不难,我认为应该这样理解。

1、p ∈ Point; x,y∈Fixnum; h∈Hash(Fixnum)
2、求映射函数GET_HASH:p -> h,且是一个1对1的函数

也就是让我们构建一个二元函数,GET_HASH(x,y),返回一个Fixnum,那么就要找到一个类似与MD5一样的算法就行了。

其他思路整理中。

作者: 逸豫    时间: 2010-8-27 12:29
本帖最后由 逸豫 于 2010-8-27 12:58 编辑

恩……最大15位么……
那就用一个100000000000000进制的数……
恩……第一位位放x,第二位位放y,转成10进制
什么效率什么的不关我事……

晕……原来是2进制15位……果然我做题不读题的优良传统依然保持么- -|||
作者: 六祈    时间: 2010-8-27 12:45
内个,16384刚好可以用14位表示,@a和@b组成28位,剩下2位用来表示4个象限,紫苏大人这个问题的条件刚好是临界值,几乎是没有额外的算法了

然后做法就支持下小幽的吧   ——→其实手头没有参考资料
作者: DeathKing    时间: 2010-8-27 13:41
本帖最后由 DeathKing 于 2010-8-27 13:44 编辑

于是,考虑到了一种新的Hash生成方法,这个生成的Hash除了特殊值(Point0,0)以外是【对齐】的。特殊的,Point.new(0,0)返回0。并且在这个函数中,0被认为是正数。去掉了关于x和y长度的字段,因为之前算错了。{:nm_3:}

这个Hash有下面的结构
____________
ABJKLMNOPQRS

A => x的正负,可选值(1、2),特殊的,0视为正数
B => y的正负,可选值(1、2),特殊的,0视为正数
J、K、L、M、N、O、P 、Q、R、S=> 描述符,可选值(0、1、2、3、4、5、6、7、8、9)

算法:
1、求取A、B
2、求取abs_x、abs_y,并转化为字符串
3、填充abs_x、abs_y,直到取得字符串长度为5
4、使用嵌入表达式组合,并使用to_i方法转换

代码:
  1. def hash
  2.   return 0 if @x == 0 and @y == 0
  3.   str = ""
  4.   abs_x = @x.abs.to_s
  5.   abs_y = @y.abs.to_s
  6.   str << (@x >= 0 ? "1" : "2" )
  7.   str << (@y >= 0 ? "1" : "2" )
  8.   while abs_x.size < 5
  9.     abs_x = "0" + abs_x
  10.   end
  11.   while abs_y.size < 5
  12.     abs_y = "0" + abs_y
  13.   end
  14.   return "#{str}#{abs_x}#{abs_y}".to_i
  15. end
复制代码
毛hash个数: 2 * 2 * 2 * 2 * 10 ^ 8 = 1600000000
理论值应该和 2 ^ ( 15 * 2 ) 一样
作者: 八云紫    时间: 2010-8-27 16:49
  1. module ReisenRSA
  2.   class Reisen_RSA
  3.     def initialize(p, q)
  4.       @p = p
  5.       @q = q
  6.       get_data
  7.     end
  8.    
  9.     def get_data
  10.       @n = @p * @q
  11.       @t =(@p - 1) * (@q - 1)
  12.     end
  13.    
  14.     def get_d(e)
  15.       (1..99999).each do |i|
  16.         return i if i * e % @t == 1
  17.       end
  18.     end
  19.    
  20.     def pack(e, number)
  21.       @d = get_d(e)
  22.       @e = e
  23.       return number ** @d % @n
  24.     end
  25.    
  26.     def unpack(e, number)
  27.       if @e != e
  28.          @d = get_d(e)
  29.          @e = e
  30.        end
  31.       return number ** e % @n
  32.     end
  33.    
  34.   end
  35. end
复制代码
好吧,整数简单的 RSA 算法. 要求苛刻. 需要 q p 是质数,  e 要小于 t =(p- 1) * (q - 1). 先判断正负,取绝对值来计算.
作者: 雷欧纳德    时间: 2010-8-27 16:52
如果是临时数据那直接用内存地址吧
作者: 贝伦卡    时间: 2010-8-27 17:29
提示: 作者被禁止或删除 内容自动屏蔽
作者: 紫苏    时间: 2010-8-28 00:22
回复 贝伦卡 的帖子

稀疏散列结构应该可以用链表实现(Google 的那个 sparsehash 似乎就是?),但确实有空时折衷的问题 o.o
作者: 贝伦卡    时间: 2010-8-28 09:40
提示: 作者被禁止或删除 内容自动屏蔽
作者: IamI    时间: 2010-8-28 13:25
本帖最后由 IamI 于 2010-8-29 09:12 编辑

一个糟糕的想法,一段糟糕的代码= =b 二进制变换摘要然后叠加
  1. # f:Defined Fixnum
  2. # return : 0b Array
  3. def turn(f)
  4.   #s = []
  5.   #begin
  6.   #  s.push f % 2
  7.   #  f = f / 2
  8.   #end until f == 0
  9.   #return s
  10.   s = sprintf("%#b", f)
  11.   a = s.scan(/./)
  12.   a.delete_at 0
  13.   a.delete_at 0
  14.   b = []
  15.   for i in a
  16.     b.push(i.to_i)
  17.   end
  18.   return b
  19. end
  20. # s:defined Array
  21. # return: zipped Fixnum
  22. def zip(s)
  23.   num = 0
  24.   begin
  25.       count = 1
  26.       l = s.pop
  27.       n = 0
  28.       loop do
  29.         break if count == 5
  30.         n = s.pop
  31.         break if n == nil
  32.         if l == n
  33.           count += 1
  34.         else
  35.           s.push(n)
  36.           break
  37.         end
  38.       end
  39.       num += (l * 5 + count - 1)
  40.       num *= 10
  41.   end until s == []
  42.   return num
  43. end

  44. x = 4001
  45. y = 2007
  46. hash = zip(turn(x)).to_s
  47. hash2 = zip(turn(y)).to_s
  48. puts (hash + “00” + hash2).to_i
  49.   
复制代码
另外,如果遇到0b101010101010101代码会超过Fixnum限定。下次想办法把01算成一位……= =b
作者: 小幽的马甲    时间: 2010-8-28 13:33
"是按照数的位数来位移么……粗略一想,位移量是变量的话,似乎难免碰撞吧?固定量 X 的位移可以保证高 X 位独立于低 X 位,而变量位移则无法保证"
那如果把位数记录下来呢?保留8位记录位数就能保证2^256范围内不会碰撞了。如果还不过那再用8位记录位数的位数,那么可以保证2^(2^256)位不会碰撞了= =这样可以无限逼近无限
作者: 紫苏    时间: 2010-8-29 01:31
回复 小幽的马甲 的帖子

没理解为什么要保留位来记录位数?
作者: 琪露诺    时间: 2010-8-29 02:46
映射……?
作者: 琪露诺    时间: 2010-8-29 03:23
本帖最后由 琪露诺 于 2010-8-29 03:47 编辑

双射……还是不懂是啥 = =
不玩了不玩了

不过……不明真相呢……
class Point
  attr_accessor:x
  attr_accessor:y
  def direct(x,y)
    @x = x
    @y = y
    return [x,y]
  end  
end
po = Point.new
hash = {}
hash[po.direct(1,1)] = 1
hash[po.direct(1,1)] = 2
hash[po.direct(1,1)] = 3
hash[po.direct(1,1)] = 4

貌似不是这么玩 = =?
OTZ……我没读懂题目 - -|||

作者: 紫苏    时间: 2010-8-29 04:10
回复 琪露诺 的帖子

class Point
    def initialize(x, y)
        @x, @y = x, y
    end
end

hash = {}
hash[Point.new(1, 1)] = 1
hash[Point.new(1, 1)] = 2
hash[Point.new(1, 1)] = 3
hash[Point.new(1, 1)] = 4

此时,实现 hash 完成题目要求之前表中有 4 个键值对;实现 hash 完成题目要求之后只有 1 个 Point.new(1, 1) => 4
作者: 六祈    时间: 2010-8-29 08:15
回复 紫苏 的帖子
紫苏大人的意思是否如此:
对于x和y皆取最大值时,hash使用30位,然而x、y并没有那么大时,则应当节约内存?
作者: DeathKing    时间: 2010-8-29 08:38
回复 六祈 的帖子


    也就是让我们去找一个线性的函数,函数值与元的长度成正比。我一直受MD5的影响,老是想让值对齐 O_O
作者: 紫苏    时间: 2010-8-29 08:53
回复 六祈 的帖子

30 位是方便在 Ruby 中测试,因为 Ruby Fixnum 只能容纳 31 位,再大了就自动转换为 Bignum,不被 Ruby 的散列表接受,但抛开语言设计限制不谈,就这个题目而言是存在能泛用于任意大小的 x、y 的解的
题目要求仅仅是完美散列 + 泛用于任意大小 x、y,你说的节约内存应该是最小完美散列的概念,即尽可能分配量值小的、分散度小(比如 1、2、3、……、9 这样的连续整数串就是分散度最小的 9 个散列码)的散列码,我手头的一种解法就是最小完美散列,但题目没有要求必须“最小” ^^
作者: DeathKing    时间: 2010-8-29 09:10
  1. irb(main):001:0> {1=>2}.hash
  2. => 13
  3. irb(main):002:0> {1=>3}.hash
  4. => 9
  5. irb(main):003:0> {19999999999999999999999999999999999999=>-11111111111111111111
  6. 111111111111111111111111111111111111}.hash
  7. => 944961355
  8. irb(main):004:0>
复制代码
so:
  1. def hash
  2. return {@a => @b}.hash
  3. end
复制代码
这和八云的借用md5是一个道理吧?
作者: 小幽的马甲    时间: 2010-8-29 09:18
回复 紫苏 的帖子
举个例子,如果用4位记录长度,不考虑负数,得到的Hash串为
1001011101
最开始的那个1是起始符没有意义不用管它
后面的0010这4位记录a的长度(2),因此后两位就是a的值(11=3)
然后从这儿一直到最后就是b的值(101=5)
最后得到a=3,b=5
加入符号也是一样的,这样应该能保证双向映射
   
作者: DeathKing    时间: 2010-8-29 09:33
回复 小幽的马甲 的帖子


    其实我之前也是用了几位数来记录长度,但是后来老板说了,如果在题目给定的域下,当然可以这样做。

但是当给定x、y∈R以后,记录长度马上就灰了。
作者: 紫苏    时间: 2010-8-29 09:35
本帖最后由 紫苏 于 2010-8-29 09:41 编辑

回复 小幽的马甲 的帖子

明白了,的确可行,果然思想无疆 o.o

又有个问题:假设需要更多的个“4位”来记录位数的位数,位数的位数的位数,……,那么如何才能知道应该在何时停止,即已经获取到了真实的 a 的位数呢?
作者: 小幽的马甲    时间: 2010-8-29 10:00
回复 紫苏 的帖子


    {:nm_1:}果然还得再记录一下这个值
Hash=50669=(1 10 0010 11 110 1101)2
同样的,1是起始符
10=2表示要往下找两次
0010表示”下一个“位数的位数是2位
后两位“11=3”表示“下一个”位数(其实是原值)的位数是3
后三位110=6表示a=6
然后从这儿一直到最后的1101=13表示b=13
最后得出a=6,b=13
作者: david50407    时间: 2010-8-29 10:14
我也来提供个想法(笑
先想想数学的二元一次方程组
ax + by = c
dx +ey = f
且a / b != d / e时 必有一组解

也就是说当x + y = k, x - y = h 时必能求出(x, y)之唯一解

class Point
  def hash
    return "#{x+y}@#{x-y}"
  end
end

也就是说当Point的x, y为固定值时Point.hash的值也会固定(不过这儿是字符串
也能从hash反推x, y
作者: david50407    时间: 2010-8-29 10:54
这样好了 咱来学学RUBY的Marshal方法
先分成这样 :
X 的位数| X的正负值( : 1, - : 2) | abs(X) | Y的正负值( : 1, - : 2) | abs(Y)
解释一下...
首先会读取 X 的位数(不考虑正负)
这部分仿照Marshal :
这里用点小技巧 (不过挺占空间的@@
假设(X的位数) <==这也是一个数, 有y位
且 y <= 2^h (1 <= (h 1) <= 9)
也就是说(X的位数) 这个数可以是1 ~ 2^8 位数
也就是说X的位数可以是1 ~ 10^(2^8 1) - 1 (表示此数庞大XD)
也就是说X 可以是1 ~ 10^(10^(2^8 1)) - 1 (更庞大了= =)
接下来依照以下顺序写入
(h 1) --> X 的位数(不足者在前补0) #=> 这当作是第一部分(X 的位数)

再来是第二部分: X的正负值( : 1, - : 2) 这很简单
第3部分依然简单abs后写入
第四第五部分直接写入
不必先写入Y的位数了

LZ应该知道为啥
不知道的再补 (笑

以上都是整数 所以能符合要求
不过x, y值越大 hash值也会越大= =
可能不会是30位 可能大可能小
作者: 紫苏    时间: 2010-8-29 11:28
两天过去了,公布一个最小完美散列的解法:



Cheers,
一群邪恶、疯狂的计算机科学家(>v<)
作者: chaochao    时间: 2010-8-29 14:20
两天过去了,公布一个最小完美散列的解法:



Cheers,
一群邪恶、疯狂的计算机科学家(>v ...
紫苏 发表于 2010-8-29 11:28
  1.         public static string xxxxxxx(long[] l)
  2.         {
  3.             string ret = "";
  4.             long[] temp = new long[l.Length];
  5.             for (int i = 0; i < temp.Length; i++)
  6.             {
  7.                 temp[i] = l[i];
  8.             }
  9.             for (int i = 0; i < 64; i++)
  10.             {
  11.                 for (int j = temp.Length - 1; j >= 0; j--)
  12.                 {
  13.                     ulong t = (ulong)temp[j];
  14.                     t = t % 2;
  15.                     temp[j] = temp[j] >> 1;
  16.                     ret = t + ret;
  17.                 }
  18.             }
  19.             ret = ret.TrimStart('0');
  20.             return ret;
  21.         }
复制代码

作者: 紫苏    时间: 2010-8-30 01:20
回复 chaochao 的帖子

呵呵,通用于 N 个域了
其实用纯粹的整数应该也行,.NET 4.0 里面支持 BigInteger
作者: 轮回者    时间: 2010-8-30 18:33
本帖最后由 轮回者 于 2010-8-30 18:41 编辑

一个例子
对于P中的元素q
q.x = 0b11111(2进制)
q.y = 0b10011(2进制)

那么,
F(Q) = 0b1101011111(2进制)

位数不相同的话,少的那个用0补上

至于负数的情况,把负当做1,正当做0
对于某个二进制数(0bX...X),如果是正数的话,就看做0bX...X0,反之,则是0bX...X1
就是说,对于z
双射 f: z -> n
z -> abs(z)*2+1/0(z>0/z<=0)
其实吧,反正N2,N,Z,Z2都是同构的,做个双射对应过去呗
作者: 轮回者    时间: 2010-8-30 18:41
回复 紫苏 的帖子


    = = 刚看到.呃,当我没说
作者: 逸豫    时间: 2010-8-30 21:07
看到之前的大大们的解法,忽然想到一种解法
首先,既然要用一个数表示唯一的一对数,那么最简单的就是直接把两个数放在一起,中间加上分隔符即可……但是数字中添加分隔符比较麻烦啊……然后就从进制入手,8进制里面是无法出现8这个数字的,那么,我们可以用10进制来表示8进制,同时中间加上8作为分隔符即可
代码如下:
  1. tempa = sprintf("%#o", a)
  2. tempa[0] = a >= 0 ? "1" : "2"
  3. tempb = sprintf("%#o", b)
  4. tempb[0] = b >= 0 ? "1" : "2"
  5. hash = (tempa+"8"+tempb).to_i
复制代码

作者: 紫苏    时间: 2010-8-30 23:58
回复 逸豫 的帖子

Orz……|||
想起一个笑话:
世界上有 10 种人:
不懂二进制的、懂二进制的以及懂格雷码的……||
作者: 后知后觉    时间: 2010-9-18 22:08
也不知道怎么的.
昨天晚上躺在床上准备睡觉的时候莫名其妙的就想到了这个帖子.
然后就莫名其妙的想到了这个方法.不知道可不可行.
除了 整数 类的对象在 RGSS 里是唯一的外.
符号 类的对象也是唯一的.
起初是用的数组的 pack("ll") 后 to_sym 弄成 符号
然后就改用 Marshal.dump 后再 to_sym

  1. class Point < Array
  2.   def initialize(x, y)
  3.     super(2)
  4.     self[0] = x
  5.     self[1] = y
  6.   end
  7.   def x
  8.     return self[0].nil? ? 0 : self[0]
  9.   end
  10.   def y
  11.     return self[1].nil? ? 0 : self[1]
  12.   end
  13.   def hash
  14.     if @hash.nil?
  15.       @hash = Marshal.dump(self)
  16.       @hash.gsub!("\0"){ "hzhj" }
  17.       @hash = @hash.to_sym
  18.     end
  19.     return @hash
  20.   end
  21. end
  22. h = {}
  23. h[Point.new(1, 1).hash] = 1
  24. h[Point.new(1, 1).hash] = 2
  25. h[Point.new(1, 1).hash] = 3
  26. h[Point.new(1, 1).hash] = 4

  27. h[Point.new(1, 0).hash] = 11
  28. h[Point.new(1, 0).hash] = 12
  29. h[Point.new(0, 1).hash] = 13
  30. h[Point.new(0, 1).hash] = 14

  31. h[Point.new(2, 0).hash] = 15
  32. h[Point.new(2, 0).hash] = 16
  33. h[Point.new(0, 2).hash] = 17
  34. h[Point.new(0, 2).hash] = 18

  35. h[Point.new(0b10001000100010001000, 0b10011001100110011001).hash] = 19
  36. h[Point.new(0b10001000100010001000, 0b10011001100110011001).hash] = 20

  37. h[Point.new(0b10001000100010001000, 0b10011001100110011000).hash] = 21
  38. h[Point.new(0b10001000100010001000, 0b10011001100110011000).hash] = 22

  39. h[Point.new(0b10001000100010001000101010101010,
  40.             0b10011001100110011001100110011001).hash] = 23
  41. h[Point.new(0b10001000100010001000101010101010,
  42.             0b10011001100110011001100110011001).hash] = 24


  43. p h[Point.new(1, 1).hash],Point.new(1, 1).hash,
  44.   h[Point.new(1, 0).hash],Point.new(1, 0).hash,
  45.   h[Point.new(0, 1).hash],Point.new(0, 1).hash,
  46.   h[Point.new(2, 0).hash],Point.new(2, 0).hash,
  47.   h[Point.new(0, 2).hash],Point.new(0, 2).hash,
  48.   h[Point.new(0b10001000100010001000, 0b10011001100110011001).hash],
  49.   Point.new(0b10001000100010001000, 0b10011001100110011001).hash,
  50.   h[Point.new(0b10001000100010001000, 0b10011001100110011000).hash],
  51.   Point.new(0b10001000100010001000, 0b10011001100110011000).hash,
  52.   h[Point.new(0b10001000100010001000101010101010,
  53.             0b10011001100110011001100110011001).hash],
  54.   Point.new(0b10001000100010001000101010101010,
  55.             0b10011001100110011001100110011001).hash

  56. exit
复制代码

作者: 森羅結界    时间: 2010-9-18 22:13
提示: 作者被禁止或删除 内容自动屏蔽




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1