evol128[Blog]

I am the bone of my code

不同层次的程序员是如何解决问题的

本文仅供娱乐,切莫当真 

感谢grant, liu, molly。 没有你们的帮忙我不可能完成这篇文章,谢谢大家

 

原题:5个水手在岛上发现一堆椰子, 夜晚睡觉后,第一名水手把椰子分为等量的5堆,还剩下一个给了猴子,自己藏起一堆。第二个水手把剩下的4堆混合后重新分为 等量的5堆,剩下一个给了猴子;自己藏起一堆。第三第四第五位水手依此办理。天亮以后,大家把剩下的椰子分为等量的5堆,剩下一个给了猴子。问原来这堆椰子最少为多少个。

 

for(i=0;i<=10000;i++){
    check(i);
}

 

printf("Please enter the number of pirates\n");
scanf("%d",&x);
for(i=0;i<=1000000;i++){  
    check(i,x);
}

 

#define NUM 5
//i是最后一次剩下的椰子个数
for(i=NUM-1;i<=INT_MAX;i+=NUM-1){
    check(i,NUM);
}

 

#define NUM_PIRATE 5
#define NUM_MONKEY 1

LARGEINT a,b,c,x,y;

//from last pirate to first, recursively solve (n-1)x=ny+1
a=NUM_PIRATE-1;
b=-NUM_PIRATE;
c=NUM_MONKEY;
for(i=0;i<NUM_PIRATES;i++){
//this function solves ax+by=c by extended-euclid algorithm
    extended_euclid(a, b, c, &x, &y); 
    b=b*NUM_PIRATE;
    c=NUM_MONKEY+NUM_PIRATE*x;
}
return NUM_PIRATE*x+NUM_MONKEY;

 

数学家

他们不写程序,他们发现椰子的数量是下面这个方程的正整数解:

(N-1)^N*x-N^{N+1}+(N-1)^{N+1}=N^{N+1}*y

接着他们手算欧几里得算法来解这个方程

 

#define NUM_PIRATE 5
#define NUM_MONKEY 1

LARGEINT a,b,c,x,y;

//这式子是不是很眼熟?
a=pow(NUM_PIRATE-1,NUM_PIRATE);
b=-pow(NUM_PIRATE,NUM_PIRATE+1);
c=(-b-a*(NUM_PIRATE-1))*NUM_MONKEY;
extended_euclid(a,b,c,&x,&y);
return x;

 

echo 15621

 

 

P.S. 本文的代码简化了很多细节,譬如说求解ax+by=c的时候,欧几里得算法只应用于c=gcd(a,b)的情况,但本题中c=k*gcd(a,b)。而且,我们需要求的是最小正整数解,而不是任意一组解。还有一个就是LARGEINT必须实现高效率乘除法,这个细节就不在这里讨论了,呵呵

Some interesting C problems 2nd edition

总之就是很多很多关于C语言的问题啦。

本文稍稍有点长,点这里慢慢看吧

一道蛮有意思的面试题

本文写于2011-03-08

感谢mike,雪瑶姐,utd帮助我完成了这篇文章

 

题目:有n个数,其中绝大部分数出现了正好3次,只有一个数只出现了1次,请写一段程序把这个数找出来

 

解法1: 建一个hash table,把number作为key,遍历数组一遍,对出现过的数进行计数,最后再遍历一遍找到只出现一次的数。

空间复杂度:length(为了时间上高效,一般length要取到Theta(n))

时间复杂度: n^2/length+0.5n(n时间遍历一遍,每次要查找n/length的hash table,最后再遍历一遍)

 

解法2:对数组进行select,对小于pivot与大于pivot的数分别计数,对不能被3整除的一边进行递归调用。

 空间复杂度:如果不在乎源数据被改变是可以仅用O(1)的空间的,但通常来讲需要O(n)空间来备份

 时间复杂度:O(n)

 

解法3(感谢雪瑶姐提供):

public static int findSpecial(int[] array){
int ones = 0;  //出现1次的1
int twos = 0; //出现2次的1
int not_threes;  //出现3次的1取反

for(int i :array){
twos |= ones & i; 
ones ^= i;
not_threes = ~(ones&twos);
ones &= not_threes;
twos &= not_threes;
}
return ones;
}

 空间复杂度O(1),时间复杂度也是O(n),不会改变原数组,应该是最好的算法了

 

 

但是,这道题的讨论还没有完。假如把题目改成“有n个数,其中绝大部分数出现了正好2次,只有一个数出现了1次,请把这个数找出来” 有一个只需遍历一遍且不用额外空间的算法:把所有数字异或一遍,最后结果就是只出现1次的那个数。 那么,可能有人会想,在这道题的条件下,是不是也存在一个类似于异或的运算符#,可以仅把所有数#一遍以后就得到结果呢?、

答案是否定的。假如存在这个运算符#,那它必须满足下面这些条件:

 A={所有32位2进制数}  #:A->A
交换律 a#b=b#a
结合律 a#b#c=a#(b#c)
存在e 对于任意a a#e=a
对于任意a a#a#a=e

我们可以证明满足上面条件的运算符不存在:

首先我们定义一个负元-a:a#-a=e
由a#a#a=e 可知-a存在,根据结合律,-a=a#a (1)
假设-a不唯一,-a=b或c, 那么a#b#c=(a#b)#c=c=(a#c)#b=b(交换律&结合律)矛盾 (2)
由(1)(2)可知,-a存在且唯一。显然,-e=e
由交换律可知,如果a#b=e=>b#a=e,所以负元这个relation是可逆的, -a=b => -b=a
因为-e=e并且A是一个有限偶数项集合
所以必定还有一个数x,-x=x
那么x#x#x=e#x=x与题设里x#x#x=e矛盾

综上所述,这个运算符并不存在

感谢UTD同学在证明上的帮助

 

中关村在线伪造的下载地址分析

事情的起因是我偶然刷了一下页面,发现整个下载点的忙碌情况全变了

刷新前:

刷新后:

这变化课真够大,我稍微看了一下2个下载链接:

http://xiazai.zol.com.cn/down.php?softid=373274&subcatid=22&site=10c&server=10c0

http://xiazai.zol.com.cn/down.php?softid=373274&subcatid=22&site=10&server=101

就换了一个argument,完全是同一台服务器同一个页面(我估计也是同一个文件)……这忽悠一下外行人还行,咱程序员可不是那么好骗的

怀着不求甚解的态度,我又去查了一下它的页面生成代码:

                        var stat_arr=new Array('吉林网通下载','山西网通下载','河南网通下载','长春网通下载',
'菏泽网通下载','承天网通下载','丽水网通下载','绵阳网通下载','茂名网通下载','大庆网通下载','昆明网通下载','天津网通下载'
);
                        var pic_arr = new Array('a12.gif','a11.gif','a12.gif','a10.gif','a11.gif');
                        for (var i in stat_arr) {
                            var num = Math.ceil(Math.random()*4);
 
                            if(i%6==0){
                                document.write('</ul><ul>');
                            }
                            if(i%2==0){
                                document.write('<li><img src="http://icon.zol-img.com.cn/soft/soft_new/'+
pic_arr[num]+'" /><a hr');document.write('ef="'+'/down.php?softid=373274&subcatid=22&site=10c&server=10c'+
i+'" nofollow>'+stat_arr[i]+'</a></li>');
                            }else{
                                document.write('<li><img src="http://icon.zol-img.com.cn/soft/soft_new/'+
pic_arr[num]+'" /><a hr');document.write('ef="'+'/down.php?softid=373274&subcatid=22&site=10&server=10'+i+
'" nofollow>'+stat_arr[i]+'</a></li>');
                            }
                        }

好吧,随机生成图片+固定格式的伪造地址……这技术含量还可以再低点儿么,至少也给我配置一下dns服务器啊!!!

[真相]对不起,我们的专业不是万能的

本文写于2011-01-31

外人通常会对学计算机的人产生种种误解,在这里我给大家澄清一下:

1.你们能修电脑么?

对于广大使用windows的同学,我很遗憾的告诉你们,windows不是我写的,它也没有公开源代码,能让我知道它工作原理的途径很有限,我真的没有办法修。这就好比你在路上捡了一个阿拉丁神灯,在实现你1个愿望后突然坏了,你希望一个机械工程师能修好它,这可能么(我打赌就算是寓言家也不会修)?非要让我修,我也只能做3件事:杀毒google重装。要说计算机专业的比非专业的有什么优势,那就是google用的比较顺手把。

使用linux和mac的同学,有问题请自己解决。这是追寻自由的代价,同时也是你的义务,你的责任,当然你也可以把它看作是一种荣耀。

至于硬件问题么,请出门左转寻求电子系同学的帮助(大概电子系的同学也需要发篇这样的文章来澄清一下专业背景)

 

 2.qq号被盗了能帮我拿回来么?

我不会说绝对不能,但这样做很难很难。大概就跟在公交车上被偷了钱包然后希望警察能抓住小偷一样难。所以,qq号被盗,请第一时间去腾讯官网寻求帮助,之后请自我反省为什么会被盗。

 

 3.被问:嘿那你能当黑客么? 然后摇头说不能。 对方的眼神唰的一下就变成了鄙视。

其实我略懂一二……计算机专业也细分了很多方向,如果对方不懂安全知识(这里我不用“黑客”这个词,因为在程序员当中它的意义是神圣的),说明他只是个应用程序员,而不是系统级的程序员。

 

 4.XXX软件你用过没? 答曰没用过。 对方吃惊:学计算机的你没用过XXX?
 恩,没有用过,我都用自己写的XXXX  <- just kidding. 学计算机的并不需要去使用那些乱七八槽的软件,一个文本编辑器就够了。即使要用,我们也倾向于使用开源软件而不是商业性质的非开源软件。

 

5. 帮忙挑一台电脑行么?

跟大家(特别是mm)普及一下科普知识:电脑和衣服鞋子化妆品是不同的,是不同的一台电脑的性能好坏,数据说明了一切,没有什么感觉不感觉的。看不懂那些乱七八槽的参数不要紧,数字越大的就是越好的。如果还是弄不清楚,那越值钱的就是越好的。购买电脑的时候请先考虑自己能够承受多少价位的电脑,然后在这个价位里面选一个看着顺眼的就可以了。

顺便说一下,女生买电脑上网看电影用的,性能什么真的无所谓,只要是市面上还在卖的电脑做这些事情完全绰绰有余。男生买电脑打游戏用的,性能什么也无所谓,再高的配置也跑不动最新出的那些游戏,有买alienware的闲钱还不如去买台x360+tv。

另外,如果真的想知道多核的工作原理,ddr3和ddr2的区别,显卡为什么重要,rpm是什么意思,欢迎找我咨询——希望你面对一大堆专业术语不会觉得boring

一个安全的个人密码系统

本文写于2011-05-28

一早发现我的gmail有从异地登录的记录,这让我很震惊。我自认为是一个很有安全观的人,密码这种东西一向是小心处理的;同时我也是一个懒人,所有网站都用了同一个密码。虽然我很莫名,但我不得不承认,我的密码在某时某地以某种方式泄露了。这次密码泄露对我来说损失惨重,我不得不手动更新了其它主要网站的密码。

痛定思痛,我决定启用一种更加安全的密码机制。其能够达到以下几个目标:

1.能够用大脑轻松记住密码或密码的构造方式

2.不同网站不同密码

3.即使密码泄露,也只影响到被泄露的那个密码,而不会被推测出其它密码

4.即使知道我的密码构成方式,也不能破解我的密码

5.即使有人通过某种神通广大的方式获得了我的所有密码,他仍然不能破解我的密码

 

基本思路:one way hash, 单向散列加密,不清楚的朋友们可以参考一下wiki (http://en.wikipedia.org/wiki/Cryptographic_hash_function)。我们平常用的md5,sha256都是比较出名的hash算法。

简单说来,这种加密算法有2个特性:

1. one way单向:就是说你没有能力(这里我避免使用“不能”这个说法,如果有几千年的寿命应该可以吧,呵呵)去根据密文来破解明文,不管给你多少信息都不行

2. collision free冲突免疫:你没有办法构造2段明文来让它们的密文相同

这样,一旦我用hash加密了我的密码,然后把密文当做新密码的话,任何人都没有办法破解我的密码

 

具体方法:

工具: hash generator(网上随便下,千万别用在线版,你发出去的http请求可不会加密),字母表转换器(自己写)。通常hash函数是将一个字节流映射到另一个字节流的,我们必须把结果转化为能够从键盘输入的字符流。

方式:alphabet(hash(key, website))  把网站名也hash进去就保证了每个网站密码不同

 

程序猿与爱情

本文写于2011-02-10

今天看到人人上好多朋友都在转载这个状态

程序猿 : zt:if ( you.Love(Me)==1 || you.Love(Me)==0 ) { love = love; love++; love--; } //你爱,或者不爱我,爱就在那里,不增不减

我都是24岁的老人了,本来我是懒得发表自己的爱情观人生观的,但是既然扯到程序了那我就来凑一脚。从programmer的角度来看,除了字面上的意思外,这段程序还可以引申出很多含义

if "you" equals to NULL, the whole program will crash. 你也许根本不了解你的爱人,你爱的他/她仅存在于你的幻觉之中,一旦你发现了真相,你的爱情将轻易崩溃

It seems that love returns an integer, but how do you know it only returns 0 or 1? It might range from -2^31 to 2^31-1! 你觉得这世上只有爱与不爱,但世事远比你想的复杂

love  = love might be omiited while compiling. 你的豪言壮语海誓山盟,在别人眼中,或许什么都不是

love++; love--; If love is a global value, it will change in some situations, such as race condition . 不变的爱情是不存在的。你觉得不会变,仅仅是因为让你改变的事情没有发生罢了

换新博客了,吼一吼

最近在家呆得百无聊赖,便想重新开始写博客。 介于本人的老博客已经一年多没更新了,干脆重新开了一个。 

没有看过我之前博客的朋友请不要担心,我会把我之前写的有价值的文章,重新编辑后发到这儿来(坦白说我真想要一个学中文的plmm帮我编辑啊^_^)。

在这个博客上,我不想介绍太多技术性的东西。我想要够通过一些互动性的文章,能够让人能觉得“写程序其实挺有趣的”。我也希望大家能够给我提供写作素材。

最后,感谢我的所有家人,朋友的支持。没有你们的支持我没法在自己喜欢的道路上走这么远。谢谢大家。