Wenbin's profileWenbin Dai's SpacePhotosBlogLists Tools Help

Wenbin Dai's Space

Wenbin

Occupation
Location
Interests

Windows Media Player

October 01

人生苦短啊

世界上好玩的东西太多了,时间精力不够啊,当然现在金钱也是问题……
September 29

个人旅游签水过

VO:去米国干嘛
Me:旅游
VO:待多久
Me:2到3周
VO:住谁那
Me:朋友家
VO:谁出钱呀
Me:我呀
VO:走吧

就照着156念了一遍嘛,啥材料都不看,干嘛还要让偶跑了一趟啊~
July 26

水立方天鹅湖

太牛了!中间穿插中国杂技、西班牙舞蹈,结尾是少林功夫大决战,黑天鹅转了20多个圈,晕……
July 22

GCJ2009 is coming...

最近几个月赛事不断啊,网易、百度,然后GCJ2009也要举行了,虽然一度说会取消,虽然现场决赛名额缩水至25人。。。
July 18

Ubuntu9.04下SMplayer播放不了DVD

应该是由于没有安装w32codecs的问题,但是Ubuntu的source里又装不了,搜到solution如下。
现在播放DVD都没有问题了,不过我的1区正版魔戒播不了,而在Windows下的SMplayer是可以的,郁闷。
 
This package is not available from the Ubuntu repositories due to licensing and legal restrictions.To play encrypted DVDs, the libdvdcss2 package is essential.

For Ubuntu 9.04 (Jaunty) Users use the following procedures

sudo wget http://www.medibuntu.org/sources.list.d/jaunty.list --output-document=/etc/apt/sources.list.d/medibuntu.list

Then, add the GPG Key using the following commands

sudo apt-get update

sudo apt-get install medibuntu-keyring

sudo apt-get update

For i386 Users install Codecs using the following command

sudo apt-get install w32codecs libdvdcss2

For amd64 Users install Codecs using the following command

sudo apt-get install w64codecs libdvdcss2

June 27

SRM286 - InfiniteSoup

http://www.topcoder.com/stat?c=problem_statement&pm=6017&rd=8083

一道很好的题目,有几个tricky的地方需要注意:

1)对于[0,k][0,k]内的任一点(x,y),该ray等同于(0,0)到(x%r,y%c)的ray。如果用brute-force枚举,即便用了KMP也会超时。

2)对于水平和竖直方向的ray,不要hard-code加到要考虑的list里面(考虑grid为{"a"}这样的情况),还是用gcd来判断。

3)用KMP而不是brute-force做string-match。

 

int gcd(int a, int b) {
    while (b != 0) {
        a %= b;
        a ^= b ^= a ^= b;
    }
    return a;
}

vector<vector<int> > suffixes;

vector<int> BuildSuffix(string pattern) {
    int lp = pattern.length();
    vector<int> pi(lp, -1);
    int k = -1;
    FOR(q,1,lp-1) {
        while (k >= 0 && pattern[k + 1] != pattern[q]) k = pi[k];
        if (pattern[k + 1] == pattern[q]) ++k;
        pi[q] = k;
    }
    return pi;
}

bool StringMatchKMP(string text, string pattern, vector<int> suffix) {
    int lt = text.length(), lp = pattern.length();
    int k = -1;
    REP(i,lt) {
        while (k >= 0 && pattern[k + 1] != text[i]) k = suffix[k];
        if (pattern[k + 1] == text[i]) ++k;
        if (k == lp - 1) return true;
    }
    return false;
}

int cnt[40][40];

class InfiniteSoup {
public:
    vector <int> countRays(vector <string> g, vector <string> words, int k) {
        int r = g.size(), c = g[0].length();

        suffixes.clear();
        REP(i,words.size()) suffixes.push_back(BuildSuffix(words[i]));

        memset(cnt, 0, sizeof(cnt));
        FOR(i,0,k) {
            FOR(j,0,k) {
                if (gcd(i, j) == 1) ++cnt[i % r][j % c];
            }
        }

        vector <int> res(words.size(), 0);

        REP(i,r) {
            REP(j,c) {
                if (cnt[i][j] > 0) {
                    string str = "";
                    int tr = 0, tc = 0;
                    do {
                        str += g[tr][tc];
                        tr = (tr + i) % r, tc = (tc + j) % c;
                    } while (tr || tc);

                    string t = str;
                    REP(k,50) t += str[k % str.length()];

                    REP(k,words.size()) {
                        if (StringMatchKMP(t, words[k], suffixes[k])) res[k] += cnt[i][j];
                    }
                }
            }
        }

        return res;
    }
};
June 11

结婚照

应大家的要求,贴上我和lp的结婚照,嘿嘿。8-)
 
From Misc
January 08

远去的列车

天下足球《再见,齐达内》里的曲子,非常好听~
 
Ce train qui s'en va 远去的列车

Je n'aurais pas du venir
J'aurais du savoir mentir
Ne laisser que ton sourire
Vivre dans mes souvenirs
J'aurais du laisser l'espoir
Adoucir les au revoir

Ce train qui s'en va
C'est un peu de moi
Qui part....qui part....

Je savais que ce serait
Diffficile mais je pensais
Que je saurai te cacher
Le plus grand de mes secrets
Mais a quoi bon te mentir
C'est dur de te voir partir

*Refrain

Et avant que ne coule une larme
Dans ton sourire qui me desarme
Je cherche un peu de reconfort
Dans tes bras je veux me blottir
Pour mieux garder le souvenir
De tout la chaleur de ton corps

*Refrain

Je n'aurais pas du venir
J'aurais du savoir mentir
NE laisser que ton sourire
Vivre dans mes souvenirs
J'ai beau essayer d'y croire
Je sais bien qu'il est trop tard

*Refrain

我本不该来
我本该学着撒谎
仅将你的微笑在记忆里封存
我本应该放弃希望
就这样和你说再见
这趟列车连同我身心的一部分
渐行渐远

我知道这样很难
但我还是得学着
将自己的感情隐瞒
但对你撒谎又有何益
只能是眼睁睁的看你远离

趁眼泪还没有滚滚落下
让我在你的微笑里放松起来
我试着寻找些许的安慰
在你的怀抱里
有我温馨的港湾
让我用尽全力去留住这记忆
留住你身体全部的温暖

我本不该来
我本该学着撒谎
仅将你的微笑在记忆里封存
我明白,我清楚
我知道这一切都以太晚

December 16

素食主义

一直以来都是肉食动物,点菜必点肉,素菜基本忽略。现在发现还是得多吃蔬菜水果啊,晚上特意点了一大盘白灼芥兰,都吃下去了。
I'm a rabbit now~
December 05

坐在老上海城隍庙熙熙攘攘的人群里面,喝了一口滚烫的馄饨汤,再咬一口生煎包,幸福指数顿时上来了。

昨天跑去西格玛听Christian老头子的Project Management的training,完了后直接在地下发廊里把头剪成了“越狱”型,结果一出门我那个悔啊,怎么这么冷的哟,北风吹啊吹,吹得偶的头皮都麻掉了,还有两只耳朵暴露在外面,委屈你们了。。。

原来冷不防北京的气温已然零下了。回想去年此时,我还在西雅图,朝思暮想着早日回来。现在想想,待在那过冬也还算不错了,貌似没有北京冷吧,呼呼。想起有一次,从公司办公室回apartment,路上也冷得不行,偶就边走边大声唱歌驱寒,把流行歌曲唱了一个来回,反正旁边也没人听得懂,哈哈。

下午training回来后,做了两道Project Euler,将AC数提到100,终于升到Level 3了,缓解了下前两天乱做SRM降了130多rating的郁闷。猛然发现肚子饿得不行,于是心满意足地出门去老上海城隍庙吃晚饭去。

3周以前吧,组里打篮球赛,偶将7个手指头都裹上了创可贴,最后半分钟两记投篮绝杀,不过也把偶的手又搞坏了,冬天到了,又该脱皮了:( 好在今年预防的早,比去年的情况好多了。每天都吃VB,吃水果,手上抹的啥都有:大宝、鱼油、维生素、乳膏,总算维持没有裂开,而且嘴唇也不干裂了。谢天、谢地、谢人。

上周大脸猫过来,呼唤奶牙出来吃饭,结果被“我是云”之。大脸怎么还是那个德性啊,都工作了还这么ws。结果被反驳之,你丫形象也太搓了,胡子多少天没刮了,无语。不过那晚“大口喝酒,大口吃肉”还是挺爽的。伢儿,你不过来和哥几个吃饭,跑去表白,结果还被拒,得不偿失了吧。hiahia~

回到屋里,打开千千听歌,把衣服洗上,然后写下了这篇无聊的blog,纯粹为了响应某些筒子的呼吁。

12月05,北京,寒。
December 01

家用电脑备份代码好方法

之前自己的笔记本挂过一次,机子上上千道ACM、TopCoder的源代码都丢了,心痛死了。
于是买了个移动硬盘来备份数据。但是源代码的备份管理起来也很麻烦。于是想到了用SVN工具来管理。
用TortoiseSVN在自己的笔记本上建一个repository,然后再弄一个客户端来管理源代码,只要有新代码就在这个客户端commit。
这样的话只要在移动硬盘上再弄一个client,每隔一段时间连上电脑update一下就行了,非常方便。
November 17

How to choose between arrays and collections (.NET)

Arrays are the fastest of all collection types, so unless you need special functionalities like dynamic extension of the collection, sorting, and searching, you should use arrays. If you need a collection type, choose the most appropriate type based on your functionality requirements to avoid performance penalties.

    Use ArrayList to store custom object types and particularly when the data changes frequently and you perform frequent insert and delete operations. Avoid using ArrayList for storing strings.

    Use a StringCollection to store strings.

    Use a Hashtable to store a large number of records and to store data that may or may not change frequently. Use Hashtable for frequently queried data such as product catalogs where a product ID is the key.

    Use a HybridDictionary to store frequently queried data when you expect the number of records to be low most of the time with occasional increases in size.

    Use a ListDictionary to store small amounts of data (fewer than 10 items).

    Use a NameValueCollection to store strings of key-value pairs in a presorted order. Use this type for data that changes frequently where you need to insert and delete items regularly and where you need to cache items for fast retrieval.

    Use a Queue when you need to access data sequentially (first in is first out) based on priority.

    Use a Stack in scenarios where you need to process items in a last–in, first-out manner.

    Use a SortedList for fast object retrieval using an index or key. However, avoid using a SortedList for large data changes because the cost of inserting the large amount of data is high. For large data changes, use an ArrayList and then sort it by calling the Sort method.

November 12

Why loving LOTR so much

1. My heroism and idealism.

2. It's a simple world, good is good, bad is bad.

3. Even if we're so small to understand why, we can change the world.

4. Love, courage, loyalty, faith.

Pay attention to the overflow of Int32

下面的代码计算Euler's Totient function。

#define MAXN 10000000

int mm[MAXN + 5];

void run() {
  FOR(i,2,MAXN-1) mm[i] = i;
  REP(i,pcount) {
    int p = plist[i];
    for (int s = p; s < MAXN; s += p) {
      mm[s] = mm[s] * (p - 1) / p;
    }
  }
}
其中pcount表示小于MAXN的素数的个数,plist则存储了这些素数。
代码looks good,但是仔细一看就会发现,虽然单个Int32的phi值是小于它自己的(这里的最大值是10^7所以看起来没问题),但是中间那一步计算
mm[s] = mm[s] * (p - 1) / p;
却有可能中间值溢出,导致最后的结果错误,改成下面酱紫就okay了
mm[s] = (LL) mm[s] * (p - 1) / p;
November 08

纳斯里征服酋长球场

阿森纳球迷可以容忍球队一年只赢两场球:一场是主场对曼联,一场是客场对曼联。

今天的比赛可以说是困难重重,阿德巴约、范佩西都不能上。不过窃以为范佩西不上反而倒是好事。

开场阿穆尼亚就手接回传球违例,被罚禁区内间接任意球,还好曼联射的也不咋的。然后第8分钟又几乎被曼联搞进去,幸好贝托越位进球无效。被打了两拳,厂队终于站稳脚跟,开始提出华丽的传接球。也亏的是曼联这种级别的对手,不会缩在后场打铁桶阵,大家放开了手脚踢对攻,厂队是不惧任何对手滴。于是有了两次极有威胁的边路传中,可惜小本子虽然很努力,还是与进球差之毫厘。不过此时就看出,纳斯里今天状态极佳,在曼联后场突来突去,游刃有余啊。

终于22分钟打破僵局,小法任意球被贝托解围,纳斯里禁区左路施舍,打中加里内维尔折射入网,1:0。但之后形式倒有点危险,加拉斯和萨尼亚先后吃到黄牌,C罗禁区左侧任意球又险些造成克里希乌龙。终于好不容易挺过上半场。

下半场开场纳斯里又给大家一个惊喜,小法中路妙传,纳斯里赶在维迪奇封铲前暴射入网,看得那叫一个爽啊。以后我厂都这么打就好了,不要老是想的要把球带进球门才作数。后面就开始处于守势了,但是反击也打得曼联很头疼,解说说的好,小法传球的那不是脚,是刀。中间阿穆尼亚英勇负伤,法比安斯基粉末登场,不过90分钟时被曼联小将拉斐尔打进一记漂亮进球。

然后裁判给出6分钟补时!不是不能超过5分钟的么!不过好歹挺过去了,继续保留夺冠希望。

纵观全场,纳斯里攻防有度,而且心理素质极佳,号称齐达内接班人并非浪得虚名啊。小法一如既往的组织全队,送出威胁球。小本子很努力,头球也有一定威胁,但脚下功夫确实糙了点,几个门前的准单刀换成大帝都不知道打进几个了。迪亚比给人眼前一亮的感觉,控球很好很稳啊,我还一直以为是糙哥呢。小老虎今天踢得一般,不过也至少保持对对方的冲击。阿穆开场脑子迟钝了,而且丫确实太小心了,不敢出击,不过英勇负伤了,大家还是给点掌声吧。还有要说的是萨尼亚的边路传中太烂了吧,换成埃布可以提两个档次了。

PS: This game began in incessant rain and ended in bright, brilliant sunlight. Smile

October 24

指环王英文剧本

强烈推荐,配有剧照,非常PP,要是做成书就好了~
October 19

SRM 422 CasePassage

http://www.topcoder.com/stat?c=problem_statement&pm=10123&rd=13513&rm=299010&cr=8347577

一道挺有意思的题目,也蛮tricky的,我在写的时候就想偏了一点,虽然过了sample数据,最后还是被人cha了 :(

题目从经典的过桥问题派生过来,只是限制更多了:

  • 只有一张地图,所以全部人过去之前每次要有若干人把图带回来
  • 桥的承受重量有上限
  • 每次过桥的一个小组里面,每个组员至少信赖一个其他组员(一个人过桥时不受这个限制)、
  • 求最短的过桥时间(一组人过桥时间按最慢的那个人算)

我第一眼看去就是一个Bit DP,给的人数上限(13)也基本符合TC的习惯。但是写的时候想偏了。我假设除了最后一次,每次至少有两个人过桥,然后从中选一个人回来。这里有一个致命的逻辑错误。考虑3个人,相互之间都互相信赖的情况。3个人体重分别为3、3、6,而桥承受重量的上限为6。那么必须是首先两个体重3的人过去,一个人拿地图回来,然后体重6的人单独过去,另一个体重3的人回来,最后再两个体重3的人一起过桥。昨天晚上我还以为自己是超时挂了,和magicpig讨论时也没有发现自己逻辑上的错误。

因为可以出现一人过桥再一人回来的情况,DP在这里按我理解就不太适用了,因为情况会变得复杂(考虑一个人过桥然后又自己跑回来的情况)。这个和前几周在组里做的一个token nested replacement的情况有点类似,但那个显然要简单许多了。在这种情况下,BFS应该是一个合适的解法。

人的状态总共是2^13,考虑地图在左边还是右边再乘以2,总的时间复杂度是2^14。magicpig昨天提到的2^26的复杂度应该是可以简化的。因为知道了桥左边人头的情况,右边的可以相应的算出来。

对于每一个状态,有3个东西需要记录,地图在左还是在右,当前桥左边的人头状况,该状态与目标状态(人全在桥右,地图也在右)的距离。每次过桥时都是枚举可以过桥的人的所有组合。后面就是一个典型的BFS的PQ实现了。

附代码如下:

#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define MAXN 13
#define INF 1000000000

class state {
public:
    int mp, mask, dist;
    state(int _mp, int _mask, int _dist) : mp(_mp), mask(_mask), dist(_dist) {};
    bool operator<(const state &rhs) const {
        return dist > rhs.dist;
    }
};

int n, bs, full, gt[1 << MAXN], mm[2][1 << MAXN];
vector<int> weight, tt;
vector<string> trust;
priority_queue <state> pq;

void init() {
    memset(gt, 0, sizeof(gt));
    gt[0] = INF;
    FOR(m,1,full) {
        int wtot = 0;
        REP(i,n) if (m & 1 << i) {
            wtot += weight[i];
            gt[m] = max(gt[m], tt[i]);
        }
        if (wtot > bs) gt[m] = INF;
        if (m & (m - 1)) {
            bool fl = true;
            REP(i,n) if (m & 1 << i) {
                int mk = false;
                REP(j,n) if ((m & 1 << j) && i != j && trust[i][j] == 'Y') {
                    mk = true;
                    break;
                }
                if (!mk) {
                    fl = false;
                    break;
                }
            }
            if (!fl) gt[m] = INF;
        }
    }
}

int doit() {
    memset(mm, 127, sizeof(mm));
    mm[0][full] = 0;
    pq.push(state(0, full, 0));
    while (!pq.empty()) {
        state cur = pq.top(); pq.pop();
        int dist = cur.dist, mp = cur.mp, mask = cur.mask;
        if (dist > mm[mp][mask]) continue;
        int s = mp == 0 ? mask : (mask ^ full);
        for (int m = s; m > 0; m = m - 1 & s) {
            if (dist + gt[m] < mm[1 - mp][mask ^ m]) {
                mm[1 - mp][mask ^ m] = dist + gt[m];
                pq.push(state(1 - mp, mask ^ m, mm[1 - mp][mask ^ m]));
            }
        }
    }
    return mm[1][0] < INF ? mm [1][0] : -1;
}

class CavePassage {
public:
    int minimalTime(vector<int> travelersWeights, vector<int> travelersTimes, vector<string> trustTable, int bridgeStrength)
    {
        n = travelersWeights.size();
        full = (1 << n) - 1;
        bs = bridgeStrength;
        weight = travelersWeights;
        tt = travelersTimes;
        trust = trustTable;

        init();
        return doit();
    }
};
September 22

Google Code Jam 08 Asian Final

早上起来,背了三本书(C++标准程序库、LRJ黑书、具体数学)就直奔G公司在清华科技园的大楼。

偶遇开复

在G公司一层领了狗牌后,坐电梯到6层。结果发现要门禁卡才能进到里边。这时两边也没有人,等了一会,终于有人上来了,发现竟然是开复,就让他帮我刷开了门,HAHA。

准备活动

到了比赛场地先setup机器。每人一个24寸的大液晶还是挺爽的,强烈呼吁MS也升级到24寸宽屏啊。旁边一人惊呼,3G内存啊,好爽。偶组里用的都是18G内存的server,没感觉。。。现场见到很多老朋友,坐在我对面的清华的OpenGL大牛,06年San Diego后又见了,看来作为是按名字字母序排的,两个“文彬”又放在了一起。旁边的是skatou,还是老样子,穿了个拖鞋就来了。。。过了一会又来了两个浙大的师弟,又是拖鞋。。。过了一会,ob、沈老师、lyt也出现了,都是作为工作人员。于是准备活动变成了大家聊天叙旧。同时还瞻仰到了ACRush、Savior、熊猫教主等偶像。

BT的xReborner

早就耳闻复旦的CSX很怪,非常BT。问skatou,盖头说,那哥们进来后,开了个浏览器,然后就敲上baidu主页,放在那。。。-_-

赛前花絮

11点半比赛,就要开始的时候,两阿姨推了一车饭过来,停在我的座位前不远。我想这下郁闷了,平常这都是吃饭的点,没的吃也就罢了,还要被诱惑,郁闷。

还有机器的摆放非常搞笑,每个人身边的主机其实是对面选手的。所以插U盘啥的都得让对面的人帮忙。组委会还特别提醒:大家重启时一定要注意啊,别把别人机器的电源给摁了。。。

比赛过程

这次题目的区分度还是不是太好。我先做的A,刚开始状态不行,繁琐的做法想了很久。后来还是清醒了下,换了一种思路,才搞定。这时看ranklist,D的小数据过的人挺多,一看,小数据permutation一下就可以,于是先把这个搞定。不过大数据就想不出来了。转看C,概率题,呵呵,后半程比赛全耗在这了,不过也没搞出来。亚洲区180人吧,1/5就是36个紧急名额。结束时排在56(最后跑完全部测试后升到51),实力确实有差距,也没啥遗憾的。

然后和skatou、ob、沈老师、lyt一起午饭。饭后后三位就嚷着要去午觉了,汗。我就和skatou在G公司楼里到处转了下,找到如下qs:xuchuan、金帅哥,miss掉如下qs:bm、mp、smell。不得不说,G公司内部的办公环境还是很棒的,期望俺们新盖的大楼。

结束

参观完毕,听了某人机器学习讲座一个,听组委会宣布了晋级名单,马上匆匆赶回公司(还好就两步路),去赶偶的commitment啊。。。

August 31

Project Euler Problem 37

Find the sum of all eleven primes that are both truncatable from left to right and right to left.

DFS搜即可,但是其实搜之前是不确定所有的值一定在Int32的范围内,所以先是用long long 来判断(当然如果有值超出了long long的范围就得用另外的做法了)。从左往右搜,所有的值都只可能由2、3、5、7之一开始,后面的值可以跟1、3、7、9 (其他的数都会制造出合数)。然后一边搜一边判断就可以了。

/**
 * Problem: Find the sum of all eleven primes that are both truncatable from left to right and right to left.
 * Algorithm: DFS
 * Author: daiwb
 * Date: 2008/08/31
 */

#include <iostream>
#include <sstream>
#include <set>
#include <cmath>
using namespace std;

#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;

int res;
int num[4] = {1, 3, 7, 9};

int string2int(string str) {
  stringstream ss;
  ss << str;
  int res;
  ss >> res;
  return res;
}

bool isprime(int val) {
  if (val == 2 || val == 3 || val == 5 || val == 7) return true;
  if (val == 1) return false;

  int mid = (int)sqrt(val + 0.5);
  if ((val & 1) == 0) return false;
  for (int i = 3; i <= mid; i += 2) {
    if ((val % i) == 0) return false;
  }
  return true;
}

bool isok(string str) {
  if (str.length() == 1) return false;

  REP(len,str.length()) {
    string s = str.substr(len);
    if (!isprime(string2int(s))) return false;
    s = str.substr(0, len + 1);
    if (!isprime(string2int(s))) return false;
  }
  return true;
}

void dfs(string str) {
  stringstream ss;
  ss << str;
  int val;
  ss >> val;
  if (!isprime(val)) return;

  if (isok(str)) {
    res += val;
  }

  REP(i,4) dfs(str + char(num[i] + '0'));
}

void run() {
  res = 0;
  dfs("2");
  dfs("3");
  dfs("5");
  dfs("7");
  cout << res << endl;
}

int main() {
  run();
}

Project Euler Problem 36

Find the sum of all numbers less than one million, which are palindromic in base 10 and base 2.

数据量不是很大(one million以下),暴力做即可。一点小trick就是偶数的二进制表示肯定是类似于1...0,所以必然不是对称的,可以略去。

/**
 * Problem: Find the sum of all numbers less than one million, which are palindromic in base 10 and base 2.
 * Algorithm: Brute Force
 * Author: daiwb
 * Date: 2008/08/31
 */

#include <iostream>
#include <sstream>
using namespace std;

#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;

bool isPal(string str) {
  int len = str.length();
  REP(i,len >> 1) {
    if (str[i] != str[len - 1 - i]) return false;
  }
  return true;
}

bool isPalDec(int val) {
  stringstream ss;
  ss << val;
  string str;
  ss >> str;
  return isPal(str);
}

bool isPalBin(int val) {
  string str = "";
  do {
    str += char((val & 1) + '0');
    val >>= 1;
  } while (val != 0);
  return isPal(str);
}

void run() {
  int res = 0;
  for (int i = 1; i < 1000000; i += 2) {
    if (isPalDec(i) && isPalBin(i)) res += i;
  }
  cout << res << endl;
}

int main() {
  run();
}

Project Euler Problem 35

How many circular primes are there below one million?

小于one million的数实际上只有6位,而且考虑到大于9的circular prime number只可能包含1、3、7、9 (如果包含0、2、4、5、6、8那么循环过后就会被2或者5整除)。简单的做法就是判断出one million以内所有的数是否为素数(很快,都不用用+2,+4筛法),然后用dfs搜索所有1、3、7、9组成的数加以判断即可。

/**
 * Problem: How many circular primes are there below one million?
 * Algorithm: DFS
 * Author: daiwb
 * Date: 2008/08/31
 */

#include <iostream>
#include <sstream>
using namespace std;

#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;

int plist[80000], pcount = 0;
int mm[1000005];

int prime(int n){
  int i;
  if ((n!=2&&!(n%2))||(n!=3&&!(n%3))||(n!=5&&!(n%5))||(n!=7&&!(n%7)))
    return 0;
  for (i=0;plist[i]*plist[i]<=n;i++)
    if (!(n%plist[i]))
      return 0;
  return n>1;
}

void initprime(){
  memset(mm, 0, sizeof(mm));
  int i;
  mm[2] = 1;
  for (plist[pcount++]=2,i=3;i<1000000;i++)
    if (prime(i)) {
      plist[pcount++]=i;
      mm[i] = 1;
    }
}

int res, len;
int num[4] = {1, 3, 7, 9};

bool isCircularPrime(string str) {
  REP(i,len) {
    stringstream ss;
    ss << str;
    int val;
    ss >> val;
    if (mm[val] == 0) return false;
    str = str.substr(1) + str[0];
  }
  return true;
}

void dfs(int idx, string str) {
  if (idx == len) {
    if (isCircularPrime(str)) {
      ++res;
      cout << str << endl;
    }
    return;
  }

  REP(i,4) {
    dfs(idx + 1, str + char(num[i] + '0'));
  }
}

void run() {
  res = 0;

  // 1-9
  res = 4;

  for (len = 2; len <= 6; ++len) {
    dfs(0, "");
  }

  cout << res << endl;
}

int main() {
  initprime();
  run();
}
August 16

跌跌撞撞进了GCJ的Regional Final

GCJ就是一个混血儿,从TopCoder派生来,罚时参照ACM/ICPC,记分参照ACM和IOI,分强弱数据。
 
总的来说,题目出的还行,类型比较多,很多数学题和几何题,不像TC放眼望去皆DP。但是没有非常明显的送分题,区分度上做得似乎也稍微差点,往往随便做两题简单的就晋级了。
 
Qualification round
随便做两题就pass了,不设人数上限。
 
Round 1
想不到偶在这里就几乎栽了跟头。每人可以参加三场round 1中的两场,其中一场晋级就ok了。偶的第一场做得奇烂无比,才800多名吧。于是又要参加当天半夜的另一场。结果开赛时偶的笔记本突然挂了。无奈,翻出公司的本本,发现没装Visual Studio。麻烦就麻烦点,那就远程到公司机子上做,结果发现连不上,原来当天清华科技园断电。。。怒了,哥我用Emacs+MingW。但MingW的安装文件下载速度也忒慢了,50m的只有十几二十k的速度。搞来搞去搞到一点,比赛时间也过了一半,想想算了,遂放弃。上网看新闻,结果看到上午的一封Congratulations信,原来Round 1每场前840名晋级,白忙活了-_-
 
Round 2
2520->1000,持续低迷,500出头的成绩晋级。
 
Round 3
1000->500,开始做的还不错,后来又卡住了。比赛结束512,郁闷而睡。
结果没想到过了几天又收到Congratulations信,原来前面有选手的source code重新run其他测试数据的时候挂了,偶又升到492了。于是搞了一把复活,进到了Regional Final。-_-
 
Round 4
Regional Final,500选手被分到各自所在洲的某个G公司的office。Asian的貌似就去北京的office,就在科技园,两步路-_-要是去Tokyo的多好啊,可以免费玩一趟。Round 4的前100就可以去California的Mountain View参加总决赛。加州还是不错滴,06年去San Diego就玩得不错,期待超常发挥了~

奥运男篮观战

托美国同事买的奥运男篮票,14号早上9点的比赛,结果6点就爬起,早早地赶到五棵松篮球馆。
进场以后发现没吃早饭亏了,因为进来就不能出来,然后场馆里卖的只有简单的饼干、香肠、牛奶什么的,根本吃不饱。好不容易看到有个点卖“满汉全席”方便面,40块一盒,人家还不卖,说是展示云云,我晕-_-
 
罢罢,咱忍,看球为主。话说五棵松球馆修的也还算不错了,大屏幕、音响啥的都还不错。偶和一干同事都是B类票,坐在上面半场,感觉好高。发现下面半场媒体区占了好大一块,可只满了1/3,真是亏啊,让我坐多好。
 
第一场西班牙对德国,没啥说的,西班牙实力占优,德国虽然一度领先,最后还是输了十几分。司机一如既往的挫啊,亏得大家那么多掌声。第二场开场仅3分钟,澳大利亚即12:1领先伊朗,宣布垃圾时间提前。偶看得实在郁闷,于是发挥微软勇于挑战的精神,尝试趁乱混入下面半场。没想到志愿者mm眼尖,虽然我只晃了一下就往里冲,还是被人家给看出来是上面的票,踏进场的半只脚又被拉了回来,郁闷-_-
 
两场结束,我和shaxuan及其同学决定继续留守,看下午中国对安哥拉的比赛。体育馆里在清人,眼看人越来越少,三人决定ws一把。(此处省略500字。。。)
 
到了下午比赛时间,上面半场果然查得很松,轻松混进场。终于看到中国队啦,姚、易、郅,还有一干小的。毕竟是主场,这场看得比较high,结果也不错,就是第二节又让大家揪心了下,中国队咋老让人这么担心呢。。。Anyway,男篮还是值得看的,起码过一段时间总能给人点惊喜,不像男足,每每看完我都有想吐的感觉。
 
话说这时候我们仨已经饥饿难当了,下午第二场立陶宛对俄罗斯几乎晕倒在球馆里。。。但其实这场打得最精彩,双方战术素养都不错。尤其是立陶宛,张指导最推崇的“合理”篮球。俄罗斯一帮白人里还有一黑哥们,据说是被AK47拉拢来比赛的,真ws啊。。。不过黑人非常猛,俄罗斯只有两套战术,一是黑人单打得分,而是黑人助攻队友得分。。。但到了后来黑人终于也体会到了啥叫“不怕神一样的对手,就怕*一样的队友”。。。
 
晚上本还有梦八的比赛,本来还想再ws一把,后来仨人都觉得饿得受不了了,遂出场觅食。球场外听到黄牛报价,普通的C类票都卖4000一张,oh my dog!想想我们只花了170大洋,看了四场,还是很值的。
 
最后还要祝愿中国队在16号的比赛里搞定德国,小组出线。偶要去沙排作志愿者,就不能在电视机前加油了。。。
August 11

拿到奥运门票了

14号早上西班牙和德国的篮球赛。托美国同事买的票,170米,很值啊。周四打算看看能不能躲过清场看中国和安哥拉的比赛。
July 13

CRD足球决赛

昨天下午比的,和APC争夺冠军。
天气相当的热。上半场首发踢了15分钟,传了一脚给shaxuan进球,但被吹越位,貌似是好球哎-_-遂被换下。shaxuan
同学半场前进了一个,MBDC 1:0领先结束半场。
下半场攻势越发凶猛了,可惜被门柱横梁挡下了不少。shaxuan同学抓住对方后卫禁区内倒钩结尾失误再下一城。
本来以为比赛就这样结束,没想到风云突变。先是本方球员一个莫名其妙的乌龙,然后又出现禁区内手球被罚点球,好像2:0以后10分钟内就被扳平了。天气相当的热,于是比赛还有15分钟时偶又替换队长Yanbo上场。抢了对方后卫一个球,在右路往门前传了一个低平球,结果Peter同学将门前一米的空门打飞-_-然后又浪费了一个单刀,技术太糙啊_-_
最后点球4:5败给了APC,悻悻而归。
 
足球是圆的。
 
PS:组里搞的PES比赛被镭哥上告至MBDC老大Stephen,Stephen说我们搞个MBDC的实况比赛吧。这下一不小心搞大了……-_-