打印一个N位二进制数的所有表示

问题的描述如下:
用户需要打印一个N位二进制数的所有表示
如:1位二进制数的所有表示:0 1
      2位二进制数的所有表示:00 01 10 11
      3位二进制数的所有表示:000 001 010 011 100 101 110 111
等等。

说明:这里N一个任意大于0的正整数。

如果大家有什么好的解决方案,可以将自己的思路或则代码贴上,大家一起学习进步。

以下是我对问题的解决方案:大家可以参考
/Files/gpcuster/calculatebinary.rar
posted @ 2007-10-17 12:41 逖靖寒 阅读(1974) 评论(61)  编辑 收藏 所属分类: 算法

  回复  引用  查看    
#1楼 2007-10-17 12:59 | 徐少侠      
public class Tow
{
private StringBuilder data;

private int length;

public int Length
{
get
{
return this.length;
}
}

public Tow(int num)
{
if (num < 1)
{
throw new Exception();
}

this.length = num;
this.data = new StringBuilder(this.length);

for (int i = 0; i < this.length; i++)
{
this.data.Append('0');
}
}

public string Grow()
{
for (int index = this.data.Length - 1; index > -1; index--)
{
if (this.data[index] == '0')
{
this.data[index] = '1';
return this.data.ToString();
}
else if (this.data[index] == '1')
{
this.data[index] = '0';
}
else
{
throw new Exception();
}
}

return this.data.ToString();
}
}

class Program
{
static void Main(string[] args)
{
int n = 3;
Tow tow = new Tow(n);

for (int i = 0; i < Math.Pow(2, tow.Length); i++)
{
Console.WriteLine(tow.Grow());
}

Console.WriteLine("OK");
}
}
你的代码很值得商量
我仔细看先

感觉一个N位的转换不需要你这么麻烦
确定一下,这里这个N假设是不大于4字节整型的是不是啊?
  回复  引用  查看    
#2楼 2007-10-17 13:00 | 徐少侠      
我的思路是将N不停地去模2
然后再除2


  回复  引用  查看    
#3楼 [楼主]2007-10-17 13:10 | 逖靖寒      
@徐少侠
N是一个任意大小的正整数
  回复  引用  查看    
#4楼 [楼主]2007-10-17 13:12 | 逖靖寒      
@徐少侠
用到%和/以后,算法的速度自然会受到影响。
可以比较一下算法的时间复杂度,
具体的可以来一个统计实际时间的时间。
  回复  引用    
#5楼 2007-10-17 13:26 | 猪怕壮 [未注册用户]
二进制从0开始不停加一不就ok了?搞的这么麻烦
  回复  引用  查看    
#6楼 2007-10-17 13:26 | 徐少侠      
刚才没仔细看清楚题目
赫赫
搞错了
惭愧
  回复  引用    
#7楼 2007-10-17 13:38 | 请输入你的姓名 [未注册用户]
just 递归
  回复  引用  查看    
#8楼 2007-10-17 13:40 | riordan      
简单的排列组合问题,有什么好讨论的?
  回复  引用  查看    
#9楼 2007-10-17 13:41 | riordan      
补充一下,这个问题的时间复杂度决定了这个N不能太大。
  回复  引用  查看    
#10楼 2007-10-17 14:00 | 徐少侠      
--引用--------------------------------------------------
riordan: 简单的排列组合问题,有什么好讨论的?
--------------------------------------------------------
有时间就研究贝

标准的排列组合算法在解决这个小问题上显得太大。

程序是程序员创造出来的,标准算法仅用来参考
  回复  引用  查看    
#11楼 2007-10-17 14:03 | 徐少侠      
例如以博主的例子
3位数的计算过程中
其实每次后面的都包含了前面的结果
有什么办法仅做最后的那次运算,从而输出所有结果呢?
速度自然快不少的。
不过要花费点存储空间了
  回复  引用  查看    
#12楼 [楼主]2007-10-17 14:31 | 逖靖寒      
@猪怕壮
这确实是一个好的思路,希望您能给出具体的实现代码^_^
  回复  引用  查看    
#13楼 [楼主]2007-10-17 14:32 | 逖靖寒      
@请输入你的姓名
just do it and test it.
  回复  引用  查看    
#14楼 [楼主]2007-10-17 14:33 | 逖靖寒      
@riordan
咱们讨论的问题确实没有很大的难度。
不过我很有兴趣看到您对这个简单问题的具体解法。
  回复  引用  查看    
#15楼 2007-10-17 14:34 | 徐少侠      
class Program
{
static void Main(string[] args)
{
int n=0;
string [][] arr;
n =20;

//初始化数组
arr = new string[n][];
int k,j;
for (k = 1; k <= n; k++)
{
arr[k-1] = new string[(int)Math.Pow(2,k)];
}
//计算并生成结果字符串
for (k = 0; k < n;k++ )
{
if(k==0)
{
arr[0][0] = "0";
arr[0][1] = "1";
}
else
{
int tmpIndex = k - 1;
int tmpLength = arr[tmpIndex].Length;
for (j = 0; j < tmpLength;j++ )
{
arr[k][j] = "0" + arr[tmpIndex][j];
arr[k][j + tmpLength] = "1" + arr[tmpIndex][j];
}
}
}
//输出结果
for (k = 0; k < n; k++)
{
foreach (string str in arr[k])
{
Console.Write(str);
Console.Write("\t");
}
Console.WriteLine();
Console.WriteLine("----------------------------");
}
Console.Read();
}
}

运行成功
  回复  引用  查看    
#16楼 2007-10-17 14:41 | aspnetx      
进行2的n次方循环,把n位数枚举出来
  回复  引用  查看    
#17楼 2007-10-17 14:49 | 徐少侠      
测试时候计算20位的
不考虑屏幕输出的时候,仅需要3秒以下就可以了
但是前提是你的机器内存要大。否则他要清理内存的。
20位需要150兆,虚拟内存157兆
21位需要增加75%的需求

自然,算法还可以改

时间和空间的矛盾这里应该能看出来啦。
  回复  引用  查看    
#18楼 2007-10-17 14:50 | 徐少侠      
--引用--------------------------------------------------
aspnetx: 进行2的n次方循环,把n位数枚举出来
--------------------------------------------------------
关键是要以二进制方式输出
  回复  引用  查看    
#19楼 2007-10-17 14:56 | aspnetx      
@徐少侠
那这样行不?外围一个循环,为n
然后单独写一个方法是把这个n转换成二进制的,套在循环体中然后做输出?
  回复  引用    
#20楼 2007-10-17 15:00 | 6545 [未注册用户]
学习了
  回复  引用  查看    
#21楼 [楼主]2007-10-17 15:03 | 逖靖寒      
@徐少侠
呵呵,看了你的算法,非常棒!
我测试了一下,算1到20位一共用了4秒(在我的机器上 T5500 2G RAM)
我测试了我的算法,只算20位的所有表示,1秒以内,21位的所有表示1秒。
  回复  引用  查看    
#22楼 2007-10-17 15:15 | 徐少侠      
--引用--------------------------------------------------
aspnetx: @徐少侠
那这样行不?外围一个循环,为n
然后单独写一个方法是把这个n转换成二进制的,套在循环体中然后做输出?
--------------------------------------------------------
每次每个数字都转换似乎效率不高哦
  回复  引用  查看    
#23楼 2007-10-17 16:03 | aspnetx      
@徐少侠
呵呵,看怎么用了.其实我也感觉这个方法要"无耻"一些,但是如果n不是大的很离谱的话,不知能否看出效率的差别.
  回复  引用  查看    
#24楼 2007-10-17 16:03 | 学海无涯,回头是岸      
'20次 760ms
'21次 1560ms
[code=vb.net]
Private Function f(ByVal n As Integer) As String
If n < 1 Then
Return String.Empty
End If

Dim str As String = "0 1"
For i As Integer = 2 To n
str = "0" & str.Replace(" ", " 0") & " 1" & str.Replace(" ", " 1")
Next
Return str
End Function
[/code]

  回复  引用  查看    
#25楼 2007-10-17 16:42 | 大石头      
呵呵,我这里两秒多跑了22位
  回复  引用  查看    
#26楼 2007-10-17 17:55 | 大石头      
数字转成二进制字符串,其实就是Convert.ToString(i, 2),可惜它暴露的方法过少,System内有个很强很完美的方法,可惜又不公开,大家看看优化一下这个程序:

static void Main(string[] args)
{
DateTime t = DateTime.Now;
String s = RendN(20, true);
TimeSpan ts = DateTime.Now - t;
Console.Write(ts.TotalMilliseconds);
Console.WriteLine("");
t = DateTime.Now;
s = RendN(20, false);
ts = DateTime.Now - t;
Console.Write(ts.TotalMilliseconds);
Console.WriteLine("");
//Console.Write(s);
Console.ReadKey();
}

static String RendN(int n, bool flag)
{
if (n < 0) return null;
int k = (int)Math.Pow(2, n);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < k; i++)
{
String ss;
if (flag)
{
ss = Convert.ToString(i, 2);
sb.Append(new String('0', n - ss.Length));
}
else
ss = IntToString(i, n);
sb.Append(ss);
sb.Append(" ");
}
return sb.ToString();
}

static String IntToString(int k, int n)
{
return (String)ParseNum.Invoke(n, new Object[] { k, 2, n, '0', 0 });
}

static MethodInfo _ParseNum;
static MethodInfo ParseNum
{
get
{
if (_ParseNum != null) return _ParseNum;
Assembly ass = Assembly.GetAssembly(typeof(System.Object));
_ParseNum = ass.GetType("System.ParseNumbers").GetMethod("IntToString");
return _ParseNum;
}
}

  回复  引用  查看    
#27楼 2007-10-17 17:55 | 徐少侠      
感情都比一个位数阿
不是从2位开始到N哦?

那继续修改,看看大家能把速度提到多少。
  回复  引用  查看    
#28楼 2007-10-17 17:58 | 徐少侠      
@大石头
学习
  回复  引用  查看    
#29楼 [楼主]2007-10-17 18:02 | 逖靖寒      
@徐少侠
呵呵,是啊,咱们都只算了一个具体的位数。
  回复  引用  查看    
#30楼 [楼主]2007-10-17 18:02 | 逖靖寒      
@学海无涯,回头是岸
学习!
  回复  引用  查看    
#31楼 2007-10-17 18:04 | 徐少侠      
--引用--------------------------------------------------
学海无涯,回头是岸: '20次 760ms
'21次 1560ms
--------------------------------------------------------
你这个东西好玩

赫赫。写程序的乐趣大致如此了
  回复  引用    
#32楼 2007-10-17 18:47 | Kevin_Shan [未注册用户]
亲自试了一下,还是蛮难的。不能到32,不然内存不够用呀。
跑21,我这不输出用了0.87,输出用了2.2

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.Diagnostics;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
fun(21);
Console.ReadKey();
}

public static void fun(short n)
{
Stopwatch sw = Stopwatch.StartNew();

uint max = (uint)Math.Pow(2, n);
char[,] result = new char[max, n];
for (uint i = 0; i < max; i++)
{
for (uint j = 0, k = i; j < n; j++)
{
if ((k & 1) != 0)
{
result[i, j] = '1';
}
else
{
result[i, j] = '0';
}
k = k >> 1;
}
}

sw.Stop();
Console.Title = sw.Elapsed.ToString();
sw.Start();

StringBuilder sb = new StringBuilder((int)(max * (n + 1)));
for (uint i = 0; i < max; i++)
{
for (uint j = 0; j < n; j++)
{
sb.Append(result[i, j]);
}
sb.Append('\n');
}

sw.Stop();
Console.Title = Console.Title + "--" + sw.Elapsed.ToString();
Console.WriteLine(sb.ToString());
}
}
}

  回复  引用  查看    
#33楼 [楼主]2007-10-17 18:58 | 逖靖寒      
@大石头
学习!
  回复  引用  查看    
#34楼 2007-10-17 20:40 | 蛙蛙池塘      
博客成论坛了,呵呵
  回复  引用  查看    
#35楼 2007-10-18 08:42 | 徐少侠      
都碰上内存问题了哦
为了保存结果,就要耗费大量内存了

目前的纪录是多少哦?
  回复  引用  查看    
#36楼 2007-10-18 08:45 | 徐少侠      
我写了一个直接显示的版本,就是说每次计算好后就显示结果
节约内存了
运行时只要十多兆
去除显示语句,速度飞快哦

  回复  引用  查看    
#37楼 2007-10-18 08:48 | 大石头      
建议大家不要合并字符串,直接算出某一个子串就可以了,那样不会占用过多资源,我们就可以得到更好的速度了。合并字符串输出,那是IO的问题。

大家可有什么办法提高我那代码中反射的性能?代码上,调用ParseNumber类是最简单的,就一句,但是必须用反射来调用,如果不用反射,性能肯定最好的,因为那个函数是Native实现的^_^
  回复  引用    
#38楼 2007-10-18 08:57 | 猪怕壮 [未注册用户]
@徐少侠

1 算出2的n次最大是多少
2 从0~2的n次最大数循环加1
3 数转二进制,然后输出二进制形式

今天有空我实验一下速度如何

  回复  引用  查看    
#39楼 2007-10-18 09:10 | 徐少侠      
@大石头
参数True,使用ToString的方式似乎速度快哦

不过还没我自己写的快,哈哈

等下贴上来

代码比较复杂哦,哈哈
  回复  引用  查看    
#40楼 2007-10-18 09:21 | 徐少侠      
@猪怕壮
你的思路和大石头上面的代码一致
我的机器上他不输出也不保存结果,仅运算需要710~750毫秒

  回复  引用  查看    
#41楼 2007-10-18 09:53 | 徐少侠      
public delegate void AddHandler();

//位类
class Bit
{
public event AddHandler overflow;
private bool _num;
public int Numer
{
get
{
if (_num)
{
return 1;
}
else
{
return 0;
}
}
}

public Bit()
{
_num = false;
}
public void Add()
{
_num = !_num;
if(!_num)
{
overflow();
}
}
}
//另外一个类做为排列做准备
class Two
{
private System.Text.StringBuilder outString;
bool f;
private int _length;
public int Length
{
set
{
if (value > 0)
{
_length = value;
}
}
get
{
return _length;
}
}

public Two()
{
outString=new StringBuilder();
_length =1;
f = true;
}

public string m2()
{
Bit[] arr = new Bit[_length];
int i, j;
arr[0] = new Bit();
arr[0].overflow += new AddHandler(Two_overflow);
for (i = 1; i < _length; i++)
{
arr[i] = new Bit();
arr[i].overflow += new AddHandler(arr[i - 1].Add);
}


while (f)
{
for (j = 0; j < _length; j++)
{
//outString.Append(arr[j].Numer);
}
arr[_length - 1].Add();
//outString.Append("\t");
}
return outString.ToString();
}

void Two_overflow()
{
f = false;
}
}

//主程序
class Program
{
static void Main(string[] args)
{
Two t = new Two();
t.Length = 20;
string outs;
TimeSpan ts;
DateTime t1 = DateTime.Now;
outs=t.m2();
ts = DateTime.Now - t1;
Console.WriteLine(ts.TotalMilliseconds);
Console.Read();
}
}

Intel Celeron M370
1500MHZ
512M DDR PC3200
Windows 2003 Server R2

20位171.875
21位359
22位750
23位1500
基本就是倍数增长了
比大石头那个快
因为算法思路不同


  回复  引用    
#42楼 2007-10-18 09:55 | 无知1 [未注册用户]
搞这样的比较有什么意义?

博客园上没人知道算法复杂度这个东西吗? NP难的问题!
  回复  引用  查看    
#43楼 2007-10-18 10:03 | 徐少侠      
@无知1
请评估一下这里的算法复杂度?
另外,我的代码似乎不是任何一本书上有的
我自己写的

如果我们学算法之后,仅仅是知道世界上有多少算法
就如同我们学习了设计模式后,自己没有能力创造模式那样

不算学好了。
  回复  引用  查看    
#44楼 2007-10-18 12:13 | 农夫三拳      
时间复杂度O(2^n) 怎么快- -
  回复  引用  查看    
#45楼 2007-10-18 12:59 | 大石头      
各位,这里的算法复杂度是不能那样算的,基数不一致呀。
  回复  引用  查看    
#46楼 2007-10-18 16:50 | 大石头      
在增加两种递归的方法,最快的速度是跑26位耗时4秒

static void Main(string[] args)
{
int Count = 26;
Console.Write("请输入位数:");
Count = int.Parse(Console.ReadLine());
DateTime t = DateTime.Now;
String s;
//s = RendN(Count, true);
TimeSpan ts = DateTime.Now - t;
Console.Write("Convert.ToString:" + ts.TotalMilliseconds);
Console.WriteLine("");
t = DateTime.Now;
//s = RendN(Count - 2, false);
ts = DateTime.Now - t;
Console.Write("IntToString:" + ts.TotalMilliseconds);
Console.WriteLine("");
t = DateTime.Now;
//s = RendM(Count, "");
ts = DateTime.Now - t;
Console.Write("递归一:" + ts.TotalMilliseconds);
Console.WriteLine("");
t = DateTime.Now;
StringBuilder ss = new StringBuilder();
ss.Append(new String('0', Count) + " ");
s = RendM(Count, ss, 1);
ts = DateTime.Now - t;
Console.Write("递归二:" + ts.TotalMilliseconds);
Console.WriteLine("");
//Console.Write(s);
Console.ReadKey();
}

static String RendN(int n, bool flag)
{
if (n < 0) return null;
int k = (int)Math.Pow(2, n);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < k; i++)
{
String ss;
if (flag)
{
ss = Convert.ToString(i, 2);
sb.Append(new String('0', n - ss.Length));
}
else
ss = IntToString(i, n);
sb.Append(ss);
sb.Append(" ");
}
return sb.ToString();
}

static String IntToString(int k, int n)
{
return (String)ParseNum.Invoke(n, new Object[] { k, 2, n, '0', 0 });
}

static MethodInfo _ParseNum;
static MethodInfo ParseNum
{
get
{
if (_ParseNum != null) return _ParseNum;
Assembly ass = Assembly.GetAssembly(typeof(System.Object));
_ParseNum = ass.GetType("System.ParseNumbers").GetMethod("IntToString");
return _ParseNum;
}
}

/// <summary>
/// 计算
/// </summary>
/// <param name="m">位数</param>
/// <param name="head">头</param>
/// <returns></returns>
static String RendM(int m, String head)
{
if (m > 1)
{
RendM(m - 1, head + "0");
RendM(m - 1, head + "1");
return null;
}
String s;
s = head + "0 ";
s = head + "1 ";
return null;
}

/// <summary>
/// 计算
/// </summary>
/// <param name="m">位数</param>
/// <param name="head">头</param>
/// <param name="n">位置</param>
/// <returns></returns>
static String RendM(int m, StringBuilder head, int n)
{
if (m > n)
{
head[n - 1] = '0';
RendM(m, head, n + 1);
head[n - 1] = '1';
RendM(m, head, n + 1);
return null;
}
head[n - 1] = '0';
//Console.Write(head);
head[n - 1] = '1';
//Console.Write(head);
return null;
}

  回复  引用    
#47楼 2007-10-18 16:50 | 猪怕壮 [未注册用户]
using System;
using System.Collections.Generic;
using System.Text;

namespace TestBoolIncreate
{
class Program
{
static void Main(string[] args)
{
Program _program = new Program();
int howlong = 20;
_program.run(howlong);
}



public void run( int x )
{
DateTime StartTime = DateTime.Now;
Double summer = Math.Pow(2, x);
for (int i = 0; i < summer; i++)
{
string value = ConverToX(2, i);
//Console.WriteLine( value );
}
Console.WriteLine("End");
DateTime EndTime = DateTime.Now;
TimeSpan intervalTimeSpan = EndTime - StartTime ;
Console.WriteLine("用时{0}秒", intervalTimeSpan.TotalSeconds);
Console.ReadLine();
}


/// <summary>
/// 转换数据到几位的string
/// </summary>
/// <param name="num"></param>
/// <param name="bitX"></param>
public string ConverToX(int bitX , int num )
{
string ReturnValue = "";

if (num / bitX == 0 && num % bitX == 0)
{
return "0";
}

while ( ! (num / bitX == 0 && num % bitX == 0))
{
int jieguo = num / bitX;
int yu = num % bitX;
ReturnValue = ReturnValue.Insert(0, yu.ToString());
num = jieguo;
}

return ReturnValue;
}



}


}
不输出结果20位38秒
  回复  引用  查看    
#48楼 2007-10-18 16:51 | 大石头      
这回比 徐少侠 那个要快点了。
还有,如果我用双线程计算,理论上耗时是现在的50% ^_^
  回复  引用    
#49楼 2007-10-18 21:38 | 无知1 [未注册用户]
@徐少侠
你根本就不懂什么是算法复杂度,而不是有没有学好的问题!
  回复  引用  查看    
#50楼 2007-10-18 22:15 | ji yang      
其实作者的算法并没错,速度慢的原因有2:

1 循环不应该:
for (int i = 0; i < Math.Pow(2, tow.Length); i++)
要把 Math.Pow(2, tow.Length) 移出来,避免每次求Pow

2 Tow类的data数据类型不应该是StringBuilder,应用char[]

修改后的代码,N = 24 只要0.75秒, 我的机器CPU:2G, 内存:512M

using System;
using System.Collections.Generic;
using System.Text;

namespace AllTuples
{
public class Tow
{
private char[] data;

private int length;

public int Length
{
get
{
return this.length;
}
}

public Tow(int num)
{
if (num < 1)
{
throw new Exception();
}

this.length = num;
this.data = new char[num];

for (int i = 0; i < this.length; i++)
{
this.data[i] = '0';
}
}

public char[] Grow()
{
for (int index = this.data.Length - 1; index > -1; index--)
{
if (this.data[index] == '0')
{
this.data[index] = '1';
return data;
}
else if (this.data[index] == '1')
{
this.data[index] = '0';
}
else
{
throw new Exception();
}
}

return data;
}
}

class Program
{
static void Main(string[] args)
{
int n = 24;
Tow tow = new Tow(n);

int count = (int)Math.Pow(2, tow.Length);

DateTime t1 = DateTime.Now;

for (int i = 0; i < count; i++)
{
tow.Grow();
//Console.WriteLine(tow.Grow());
}

Console.WriteLine(DateTime.Now - t1);
Console.WriteLine("OK");


Console.Read();
}
}
}


  回复  引用  查看    
#51楼 2007-10-18 22:17 | ji yang      
  回复  引用  查看    
#52楼 2007-10-18 22:31 | ji yang      
原算法还是有一些小问题

当N为3时,如果数一下Grow里的循环次数,会发现循环了14次。
而这样写,只要7次,当N大了以后,就会影响速度了。

public char[] Grow()
{
int pos = length - 1;

while (pos > 0 && data[pos] == '1')
{
data[pos] = '0';
pos--;
}
data[pos] = '1';

return data;
}
  回复  引用  查看    
#53楼 2007-10-18 23:11 | 大石头      
同意楼上的,或许我那里的第四种方法把StringBuilder改为char应该快点吧
  回复  引用  查看    
#54楼 2007-10-19 12:38 | 徐少侠      
--引用--------------------------------------------------
大石头: 这回比 徐少侠 那个要快点了。
还有,如果我用双线程计算,理论上耗时是现在的50% ^_^
--------------------------------------------------------
双线程计算
最好是双核
单核的似乎效果不明显
  回复  引用  查看    
#55楼 2007-10-19 17:32 | 大石头      
把StringBuilder改成char后,更快了,5秒就可以跑28位了

现在正在写一种新的以空间换时间的算法
  回复  引用  查看    
#56楼 2007-10-19 17:48 | 徐少侠      
越来越快了哦

大家加油
  回复  引用    
#57楼 2007-10-19 21:20 | Andy1990zx [未注册用户]
常来学习
  回复  引用  查看    
#58楼 [楼主]2007-10-19 22:51 | 逖靖寒      
@Andy1990zx
哈哈,欢迎你来。
  回复  引用    
#59楼 2007-11-22 19:07 | desperado_spz [未注册用户]
@ji yang
1 循环不应该:
for (int i = 0; i < Math.Pow(2, tow.Length); i++)
要把 Math.Pow(2, tow.Length) 移出来,避免每次求Pow

记得CLR在编译为IL时会自动将for循环中的边界条件缓存起来的,所以不会每次求Pow
  回复  引用  查看    
#60楼 2008-06-23 08:45 | U2U      
用位运算吧
  回复  引用  查看    
#61楼 [楼主]2008-06-23 10:28 | 逖靖寒      
@U2U
呵呵,能说说你的思路吗?

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-10-17 14:29 编辑过


相关链接: