2007年1月24日

前几天,学校 BBS 上有人提了一个小问题,本来没想做,后来看了看回文,不自觉的考虑了一下。

题目如下:
有 36 匹马,每次比赛只能有 6 匹马参加,最少进行几次比赛可以得到 36 匹马中跑得最快的前 6 名。限制有:1)没有表 (每次比赛只能记名次);2)每匹马的速度在任何比赛中速度不变。

我的思路:
1) 36 匹马分 6 组,每组 6 匹,进行初轮比赛,记录各组内部名次;
2) 根据初赛结果,把每组第 1 名组合到一起,比赛,记录名次,并给每匹马一个权值,权值和名次相同;
3) 按照初赛的结果和比赛 2) 的结果,为每匹马赋一个权值,规则是:每匹马的权值是它初赛所在组的前一名的权值 +6。比如某匹马初赛时在小组内得了第 4 名,而它所在的小组的第 1 名在比赛 2) 中得了第 5 名,则该马的权值为:
5[小组第 1 的权值] +6[小组第 2 的权值] +6[小组第 3 的权值] +6[小组第 4 的权值] = 23;
4) 选择当前权值 >1 的最小的 6 匹马比赛,记录名次,根据此次名次更新这 6 匹马的权值,然后根据此次名次和初赛结果更新其他马的权值 (不包括权值为 1 的马),规则同前;
5) 判断当前权值 =1 的马的个数,=6 则结束,否则转到 4)。

由上述思路得到的次数为:
6[1)] + 1[2)] + 5[5 次 4)] = 12
不知能否还能更简,听说有 8 次的,不知是否可行...
posted @ 2007-01-24 16:30 ScorpioLove 阅读(255) | 评论 (1)编辑

2007年1月11日

刚进一个项目组, 不熟悉代码, 产品跑个三四天就报内存不够, 肯定是 code 里面有问题, 怎么找到问题的所在?

-- 找 static 的東西,特別是 static 的 Collection。

-- 是不是因为 GC 忽略 static 的内容?

   -- 這個是肯定的,程序員很容易就犯錯誤,比較常見的就是 singleton 的 manager 問題,有些 static 的 Collection,往裏麵 put 了,卻沒有 remove,還是 static 的……

   -- 不是 gc 忽略 static 的内容。因为 static 的 collection 的生命周期和程序的运行周期一样长,如果在 static 的 collection 中有其他对象的引用,那么 gc 就永远不会收集里面的内容,即使在其他地方也没有用到了。很经典的内存泄漏就是在 Stack 的设计中,弹出一个 element 的时候,没有把其中的引用置为 NULL。在缓存设计中也会有这个问题,解决类似问题的一个办法是采用弱引用。

-- 找那些 singleton 會找出點東西

-- 一般的 Java 里面内存泄露都与 Collection 有关,常见的可能是 map 里面放了太多的东西,不用的时候又没有 remove 掉;所以 Java 里面有 WeakHashMap 这个类以及相关的一些类、接口


posted @ 2007-01-11 12:34 ScorpioLove 阅读(201) | 评论 (0)编辑
 
这是在 2006 年 11 月 17 日浏览小百合时得到的,当时上不来,就暂存在我的信箱里了。

南京大学小百合站,Algorithm 版,x->18->1 和 x->18-2。

x->18->1:(两处红色标记是我个人加上的,怀疑原文有误,即若有 10 和 100,则前面不应有 90 和 1800)
令结果为 x
x=log2+log3+...+log9
  +90+log1.1+log1.2+...+log9.9
  +1800+log1.01+log1.02+...+log9.99
  +3
 =∫logx dx (从2到10)
  +90+10∫logx dx(从1.1到9.9)
  +1800+ 100∫logx dx (从1.01到9.99)
  +3
 = ...
后两次积分上限的不同是考虑到修正

x->18->2:
x=(∫log(x)dx(2--1001)+∫log(x)dx(1--1000))/2
 =((x*log(x)-∫xdlog(x))(2--1001)+(x*log(x)-∫xdlog(x))(1---1000))/2
 =2567.857000.....


我个人的想法:

经过上述两个方法,我猜想求解一个数的位数可以求解该数对其基数的对数(此处是以 10 为基数的),找了几个数写了写,发现可以:
一个以 b 为基数的数 N,在以 b 为基数的计数系统中的位数 l,可以通过求 N 对 b 的对数求得。
具体为:l=floor[log b (N) + 1],即求对数,结果加 1 后向下取整。
例如:
  • length(123456789)10=floor[lg(123456789)+1]=floor[8.091514977+1 ]=9
  • length(100000000)10=floor[lg(100000000)+1]=floor[8+1]=9
  • length(10101)2=floor[log 2 (23) + 1]=floor[4.523561956+1]=5  (10101)2=(23)10
再回到求解 1000 的阶乘的位数上,则根据上面的说明,有:(设 1000 的阶乘结果为 N)
length(N)10=floor[lg(N)+1]
           =floor[lg(1*2*3*...*999*1000)+1]
           =floor[lg1+lg2+lg3+...+lg999+lg1000+1]
           =floor[lg2+lg3+...lg999+lg1000+1]    <= lg1=0
这时问题转到了求解 lg2+lg3+...+lg999+lg1000 的累加上面。

对于这一方面我不是很清楚(高等数学基本都不记得了...),不过根据前面两篇文章,好像有:
∑(N=2..1000)lgN = ∫lgxdx (x=2..1000)

如果成立的话,则根据 lgx = lnx/ln10 有:
∫lgxdx (x=2..1000) = (1/ln10)*∫lnxdx (x=2..1000)
                   = (1/ln10)*[x*lnx - ∫xd(lnx)] (x=2..1000)
                   = (1/ln10)*[x*lnx - ∫dx] (x=2..1000)
                   = (1/ln10)*[x*lnx - x] (x=2..1000)
                   = x*(lnx - 1)/ln10 (x=2..1000)

然后由牛顿-莱伯尼茨公式可以得到:(也不知道是否能在此处应用...)
∫lgxdx (x=2..1000) = 1000*(ln1000 - 1)/ln10 - 2*(ln2 - 1)/ln10
                   = [1000*(6.907755279 - 1) - 2*(0.693147181 - 1)]/ln10
                   = [1000* 5.907755279 - 2*(-0.306852819)]/2.302585093
                   = [5907.755279 - (- 0.613705639)]/2.302585093
                   = 5908.368984639/2.302585093
                   = 2565.97204707

将结果代回前面的式子:
length(N)10 = floor[2565.97204707 + 1] = 2566

原先通过 Python 计算过 1000 的阶乘,位数为 2568 位。

考虑前面推算的过程中把 x=1 时 lg1 略掉了,理论上不应产生区别,但若要是不略掉该项时,则结果变成:
∫lgxdx (x=2..1000) = 1000*(ln1000 - 1)/ln10 - 1*(ln1 - 1)/ln10
                   = [1000*( 6.907755279 - 1) - 1*(0 - 1)]/ln10
                   = [1000*5.907755279 - 1*(-1)]/2.302585093
                   = [5907.755279 + 1]/2.302585093
                   = 5908.755279/2.302585093
                   = 2566.13981258

length(N)10 = floor[2566.13981258 + 1] = 2567

可见结果略有不同,但都与正确结果有一点小偏差,个人认为思路是正确的,方法还有待改进。同时看到第二篇引文的结果非常接近,不过我还不理解,还需在琢磨琢磨。

还要再好好看看高等数学...


posted @ 2007-01-11 12:14 ScorpioLove 阅读(1736) | 评论 (4)编辑
 
一直很无奈,怎么也登录不了我的 blog,同学说用代理可以上,可是这几个月来,我基本上隔一两天就点击一下,无论用不用代理,始终连不上,浏览器显示一直连接的状态,持续几分钟甚至十几分钟...

昨天晚上,再次点击,竟然很快就上了...

不管怎么样,总算还是能用了,不过如果再出现这样的情况,可能就得考虑搬家了... 倒不是一定要写些什么东西,关键是自己原来写的一些东西,自己都没法看,看来还是要备份啊...

好了,先把最近记录的一些东西整理整理。

posted @ 2007-01-11 12:05 ScorpioLove 阅读(62) | 评论 (0)编辑

2006年11月6日

原文链接:http://blog.rogerz.cn/archives/375

1. 设定 tab 的位置

:set tabstop=4

2. 输入 tab 时自动将其转化为空格

:set expandtab

如果此时需要输入真正的 tab,则输入 Ctrl+V, tab,在 Windows 下是 Ctrl+Q, tab

3. 将已存在的 tab 都转化为空格

:retab

4. 设定编辑模式下 tab 的视在宽度

:set softtabstop

这不改变 tabstop,但让编辑的时候 tab 看起来是指定的宽度,输入 tab 时会插入的 tab 和空格的混合,比如 tabstop=4softtabstop=10,那么插入 tab 时会将光标移动 10 个字符,可能会是两个 tab 加两个空格,这对 backspace 也有效。

5. 解决 shiftwidth 和 tabstop 不等时的麻烦

:set smarttab

在行首输入 tab 时插入宽度为 shiftwidth 的空白,在其他地方按 tabstop 和 softtabstop 处理

6. 将 tab 显示为可见字符

:set list listchars=tab:>-

tab 将被显示为 >—- 的形式

7. 只在编辑特定类型的文件时展开 tab

将如下代码加入 ~/.vimrc

autocmd FileType * set tabstop=4|set shiftwidth=4|set noexpandtab
autocmd FileType python set tabstop=4|set shiftwidth=4|set expandtab

参考文章:

  1. VIM Tip#12
  2. :help tabstop
posted @ 2006-11-06 21:16 ScorpioLove 阅读(369) | 评论 (0)编辑

2006年11月2日

ASCII 码表 I (前 128):

ASCII 码表 II (扩展, 128 之后):


posted @ 2006-11-02 16:47 ScorpioLove 阅读(222) | 评论 (1)编辑

2006年10月27日

前几天同学提到编程实现排列组合的算法, 要能把排列组合的结果输出. 想了一段时间未果, 同学的思路是使用递归, 比如求解找出 n 个数中 m 个数的排列和组合:

 step a) 求解后 n-1 个数中 m 个数的排列组合; // P(n-1, m) 或 C(n-1, m)

 step b) 求解后 n-1 个数中 m-1 个数的排列组合; // P(n-1, m-1) 或 C(n-1, m-1)

 基本情况: m 为 0 时返回.

整个过程复杂度 O(n^2), 空间需要 P(n, m)*m 或者 C(n, m)*m.

下面是从网上找到的排列组合算法, 我觉得挺巧的, 最后面是一个利用 C++ STL 库函数实现的排列组合算法 (与前面的无关), 复杂度未知 (应该取决于库函数的内部实现吧).

1.1 组合算法

    本程序的思路是开一个数组,其下标表示 1 到 m 个数,数组元素的值为 1 表示其下标代表的数被选中,为 0 则没选中。

    首先初始化,将数组前 n 个元素置 1,表示第一个组合为前 n 个数。

    然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。

    当第一个“1”移动到数组的 m-n 的位置,即 n 个“1”全部移动到最右端时,就得到了最后一个组合。

    例如求 5 中选 3 的组合:
  1   1   1   0   0   //1,2,3
  1   1   0   1   0   //1,2,4
  1   0   1   1   0   //1,3,4
  0   1   1   1   0   //2,3,4
  1   1   0   0   1   //1,2,5
  1   0   1   0   1   //1,3,5
  0   1   1   0   1   //2,3,5
  1   0   0   1   1   //1,4,5
  0   1   0   1   1   //2,4,5
  0   0   1   1   1   //3,4,5

1.2 全排列算法

    从 1 到 N,输出全排列,共 N! 条。

    分析:用 N 进制的方法吧。设一个 N 个单元的数组,对第一个单元做加一操作,满 N 进一。每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没有则说明得到了一个排列方案。


2 C++ STL 的排列组合方法实现: 最近一直在看 << C++ 标准程序库 >> 这本书,在看到"变序性算法"部分的时候,发现两个函数 next_permutation, prev_permutation 对于我们平时处理排列组合的问题很有帮助,根据书上的介绍写了两个个测试函数:

void permutate()
{
    vector<
int> v;

    INSERT_ELEMENTS(v, 1,3);

    PRINT_ELEMENTS(v, "myself: ");
 
    
while(next_permutation(v.begin(), v.end()))
    {
        PRINT_ELEMENTS(v, "");
    }
}

void conbine()
{
    vector<
int> v;

    INSERT_ELEMENTS(v, 1,3);

    PRINT_ELEMENTS(v, "myself: ");
 
    sort(v.begin(), v.end(), greater<
int>());//增加排序(降序)
 
    
while (prev_permutation(v.begin(), v.end()))
    {
        PRINT_ELEMENTS( v, ""
);
    }
}
posted @ 2006-10-27 18:04 ScorpioLove 阅读(387) | 评论 (1)编辑
 
     摘要: 前几天无聊, 舍友拿来一玩具"九连环". 把玩之中, 觉得过程类似"汉诺塔", 遂考虑写个程序模拟一下.

其实过程挺简单的, 关键在于, "九连环"中除了第一个环, 其它所有的环都套着它前面的环, 因此, 要操作第 n 个环 (安装或者拆卸), 则第 n-1 个环必须在上面, 而第 n-2 个之前的所有环都不能在上面.

两个关键函数:  阅读全文
posted @ 2006-10-27 17:02 ScorpioLove 阅读(112) | 评论 (0)编辑
 
前一段时间看到一个往年程序竞赛的题解, 有一个题目说的是求 100 的阶乘末尾有多少个 0. 题解中给出的讲解提到, 一个数 n 的阶乘末尾有多少个 0 取决于从 1 到 n 的各个数的因子中 2 和 5 的个数, 而 2 的个数是远远多余 5 的个数的, 因此求出 5 的个数即可. 题解中给出的求解因子 5 的个数的方法是用 n 不断除以 5, 直到结果为 0, 然后把中间得到的结果累加. 例如, 100/5 = 20, 20/5 = 4, 4/5 = 0, 则 1 到 100 中因子 5 的个数为 (20 + 4 + 0) = 24 个, 即 100 的阶乘末尾有 24 个 0. 其实不断除以 5, 是因为每间隔 5 个数有一个数可以被 5 整除, 然后在这些可被 5 整除的数中, 每间隔 5 个数又有一个可以被 25 整除, 故要再除一次, ... 直到结果为 0, 表示没有能继续被 5 整除的数了.

今天无意间看到有人问 1000 的阶乘有几位数, 上来就用上面的方法算了一下, 249, 又读一遍题目, 才发现是求所有的位数, 想了好久也没有思路, 无奈用 Python 算了一把, 结果有 2568 位, 可是依然不知道如何计算 1000 阶乘的位数, 还好通过结果验证了末尾有 249 个 0 是正确的...

--------

后来浏览小百合时找到了一个方法,参见: 后续, 求解


posted @ 2006-10-27 16:35 ScorpioLove 阅读(1798) | 评论 (3)编辑

2006年9月27日

不知不觉,又有小一个月没有更新我的 blog 了,也不是不想写,关键是心里想着,做完一个事情,或者看完一个东西,然后再写点,可能会更有收获。不过现在又快月底了,马上就到十一假期,觉得应该来个总结,然后计划一下后面的事情。

总得来说,最近这一个月干成的事好像不是很多,第一个应该是配置好了支持 CJK 的 tex 系统,虽然不是很麻烦,但对一个新手而言,安装配置前资料文档的查阅之类的预备工作也是挺琐碎的(有时都有点闹心),具体细节参见:
Debian etch 下安装配置支持 CJK 的 tex 系统

第二件事是装 java 的开发环境,自从 SUN 公司开放 Java 源代码,制订新的 DLJ 以来,java 开始慢慢导入各种 linux 的发布版,debian 就可以使用 apt-get 安装,而不用再去下载二进制包自己安装了:
Debian 下安装 Java 开发环境

剩下的事情主要是总结暑假看的 C/C++ 语言教程,看书,和同学一起 TopCoder。

C 语言教程主要是 C by DissectionThe art and Science of C,感觉还不错,读起来挺快,容易理解,还涉及一部分 C 与 C++ 之间的比较。从图书馆借的书快到期了,决定再看一遍,边看边记,正好练习一下 latex,希望能最后能整理出一个象样的文档。还有一本是同学的 The C Programming Languange,这本书很薄,但读不快,我想和自己总结的文档一起对照着读,效果可能会好一点,然后再修改一下总结的文档,这应该是今后一段时间要完成的任务了。

C++ 语言教程主要是 C++ Distilled,短小精悍,方便总结,不过要想深入理解还是要找本厚点的。争取也能整理一份文档,毕竟好记性不如烂笔头么。

十一假期及以后的任务,首要就是完成上面提到的总结任务,总结成文档后再结合 C/C++ 作者的书,以及 APUE 2 等书籍慢慢研习。
posted @ 2006-09-27 17:28 ScorpioLove 阅读(85) | 评论 (1)编辑