存档

‘未分类’ 分类的存档

ProjectEuler解题笔记-Problem 12

2010年11月20日 没有评论

ProjectEuler是与mathchallenge类似的oj系统,提供一些数学和计算机相关的问题。题目难度从易到难都有,工作之余,做一两道题目也是很不错的休闲,还能重拾遗忘的数学知识。另外网站还提供了问题分析,看看别人的优化思路,也是一种提高。

题目

The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

Let us list the factors of the first seven triangle numbers:

1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28

We can see that 28 is the first triangle number to have over five divisors.

What is the value of the first triangle number to have over five hundred divisors?

思路

题目很好理解:首先定义了什么叫triangle number,然后提出问题:找出含有500个因子的第一个triangle number。

Naive方法

暴力分解,很快代码就能写出来。

// 暴力计算因子个数
int get_factor_count( uint64 num )
{
    uint64 count = 0;
    for ( uint64 i = 1; i< num; i ++)
    {
        if (i*i > num)
        {
            break;
        }
        if (num % i ==0)
        {
            count ++;
            if (i * i != num)
            {
                count ++;
            }
        }
    }
    return count;
}
void problem12()
{
    uint i=2;
    do{
        if( get_factor_count(i) >= 500 )  {
            printf("%u\n", i);
            return;
        }
        else if( i % 10000 == 0 )  {
            printf( "%d %u\n", i, get_factor_count(i) );
        }
    }while( i++ );
}

但跑到1分钟还没出结果,无奈的cancel掉。

分析优化

根据题意,三角数是从1累加的值,根据等差公式,第n个triangle num的值为n(n+1)/2。发现这里面有些文章可以做:

1. n和n+1必然有一个为偶数,也就是说,它们中的一个会被2整除。

2 . 除1外,n和n+1没有公共因子。

因此,我们可以得到这个数的因子个数为

P(Tn)=P(n/2)*P(n+1) n为偶数
P(Tn)=P(n)*P( (n+1)/2 ) n为奇数

根据这一思路,我们就能得到新的函数。这样我们只需要平方根级别的计算。

void problem12()
{
	const static int N = 100000;
	int a[N];
	for( int i = 2; i<N; i++ )
	{
		if( i % 2 ==0 )
			a[i]=get_factor_count(i/2);
		else
			a[i]=get_factor_count(i);
	}
	for( int i = 2; i<N-1; i++ )
	{
		if( a[i]*a[i+1]>500)
		{
			printf("%lu\n",i*(i+1)/2 );
			break;
		}
	}
}

经过优化,在我的机器上500ms就计算出了答案。

进一步优化

由于时间已经满足要求,就未进一步优化。

如果需要,下手点应该是get_factor_count函数了。参考这篇文章

其他

关于三角数的奇妙性质

分类: 未分类 标签: ,

VPS的ssl安全twitter api

2010年10月16日 2 条评论

之前上twitter主要是用tweetdeck,配合google app engine的gtap,但从这周开始,我的gae代理时好时坏,经常无故被rst。为了方便使用,同时安全起见,决定放弃gae。正好上了newtwitter和echofun,用了几天,还是不能放弃新tweet的通知,也忍受不了echofun的丑陋字体。折腾了一下,觉得还得用api。正好前一阵时间buyvm特价,顺手买了一个15刀一年的白菜VPS,于是准备自己架一个支持https的twitter api。

系统是ubunutu,开工。

一 安装php+lighttpd

sudo apt-get install lighttpd
sudo apt-get install php5-cgi
sudo apt-get install curl libcurl3 libcurl3-dev php5-curl
sudo apt-get install php5-mcrypt # 用于加密本地数据

二 开启SSL支持

openssl req -new -x509 –keyout /PATH/server.pem -out server.pem -days 365 –nodes #生成山寨证书,PATH视情况及个人爱好放置

修改lighttpd.conf(默认在/etc/lighttpd目录下),添加:

$SERVER["socket"] == ":443" {
#server.document-root = "/var/www/https"
ssl.engine                 = "enable"
ssl.pemfile                = "/etc/lighttpd/server.pem"
}

重启lighttpd

sudo /etc/init.d/lighttpd force-reload

三 将ssl证书设置为可信

用https打开https://domain/,浏览器会提示证书不是由可信CA颁发的(当然了,是我们自己山寨的嘛)。为了避免每次使用都确认,我们点将证书添加至可信区域。

(update:据http://www.naga61.com/ssl-finished-out-share-personal-twitter-api介绍,可以申请免费证书)

四 测试

添加info.php文件至htocs目录:

<?php
phpinfo();
?>

打开url: https://domain/info.php,如果不需要点确认,就能看到一个长长的表,再搜索一下有curl,我们的lighttpd和php就OK了。。

五 twip

twip的文档写的太烂,所以网上有n多的twip使用手册,大家自行搜索,这里就不再重复了。也可以猛击这里看我为你选择的一篇。

注意:

1. 选用o模式

2.注意oauth目录的权限

3.修改lighttpd.conf,并重新load配置

url.rewrite-if-not-file += ( "^/twip/(.+)$" => "/twip/index.php/$1" )

六 设置为私用

按文档说明,只需要设置private_api即可,但初看了一下php代码,没有相关的功能,因此,只能先采用修改oauth目录权限的方式限制,等待@yegle后续开发。

注:通过google/baidu参考过大量网页。

有任何问题,可以联系email或者twitter

分类: 未分类 标签:

linux发送带附件html格式邮件

2010年8月7日 没有评论
echo '<html>abc</html>'|mutt recv@xxx.com -a file attach -s 'titile'  -e 'set content_type="text/html"' 

注意, mutt版本需要1.5+

分类: 未分类 标签:

编译检查应用

2010年8月7日 没有评论

一个升级项目里,需要更改帐号体系,简单的说,就是帐号体系由32位帐号体系切换到另一部门的64位体系。系统里面一般都会对id类型做定义:typedef user_id_t uint32_t;看起来是个简单任务,只需要更改一下typedef user_id_t uint64_t,就可以完成。但实际情况远非如此。比如数据固化层需要扩充字段类型,再比如为了应付大访问量,某些服务会采用bitmap的形式在内存中维护数据,在64位体系下需要修改内存数据组织方式。

涉及底层体系的升级,牵一发而动全身,但本文只关注一个很小的问题,变量size。我们考虑以下场景 :

1. 并不会所有地方,程序员都用typedef,假如存在这样的代码段:

userid_t id_a;  // typedef后此处为64位

//....code....

uint32_t id_b;
id_b = id_a;

我们会发现赋值后,数据精度会丢失。这个错误可以通过加-Wconversion参数来警告。

2. 如果原有函数接收32位数据,但实参id已经是64位了:

// ErrorCode 1
pPacket->id = htonl(id)

// ErrorCode 2
void foo( uint32_t id )
{
    // ...code...
}

foo( id )

在上面的例子中,数据传递过程高32位数据丢失。类似的代码如果有一处遗漏,功能方面就会出问题,增加调试和定位的工作量。

这样的错误,比较适合用编译器检查。但gcc4.3以后才支持检查此错误,而公司所广泛使用的gcc版本是3.4。(实际也尝试过用lint工具,但由于报的错误太多而放弃)。

第一步 编译安装:

比起升级glibc,升级gcc相对简单,上官网下载了一个gcc 4.3,基本按照常规的步骤即可完成。

由于gcc与硬件平台相关,就不给出具体参数了,玩过交叉编译的同学估计都很熟悉。如果对gcc编译不熟练的,注意下configure时,一是要选对host,让gcc可以正确的生成代码,如果不知道机器的host类型,可以查看现有的gcc编译参数,也可以在/usr/include目录下找到;另外,一定要加disable-multilib,这样就只会为本机产生代码。

第二步 gcc切换

由于我们只用gcc4做语法检查,真正生成代码还是由gcc3完成,因此,需要两个环境可以简单切换。需要注意的是,仅仅通过改PATH变量,还是不够的,还需要更换指向的header/so。

第三步 过滤boost错误信息

升级后,使用新版的gcc编译时,会发现boost有大量的警告,非常烦人。其中有一部分,像this指针的shadow定义,可以通过相应的选项-Wno-xxx去掉,有一些是无法去除的;就算可以显式通过选项指定,但有可能这些检查是我们所需要的。因此,我修改了出错显示代码,在打错出错信息的时候,检查一下调用栈,如果最底层(也就是出错的地方)的路径是boost目录,直接return。重新编译后,boost错误信息就被过滤掉了。

完成了这几步,我们的目的就基本达成了,可以做赋值size编译检查,过滤了boost信息,并且可以和vim等编译器结合。

分类: 未分类 标签:

Google的PAC-MAN主页

2010年5月22日 没有评论

今天上Google时,赫然发现主页居然是吃豆人,更让人意外的是:耐心等待一会,它居然可以玩:

image

 

原来这是Google为了纪念PAC-MAN 30周年而特意制作的。小时候就很喜欢玩这个游戏,很开心玩了一会,不亦乐乎。只可惜三条命,现在水平大降,玩一会就死了。

但折腾的时候,发现了两个好玩的地方:

1. 多按一次页面上的Insert Coin,会进入双人模式,屏幕上会出现两个pac-(wo)man,一个用方向 键控制,一个是wasd控制

image

2. 发现它居然是用js和图片做出来的,完全保证了跨平台性、很赞。

分类: 未分类 标签: