作者: yylogo

  • USACO 1.2.1 Milking Cows

      这一次刷题目纯粹是为了Noip的复赛,因为不知道Noip复赛是否能够使用qsort函数,所以就只能自己写了,在函数实现方面出现了不少错误,原计划时提交一次就AC的,但是却提交了4次,下面先贴出思路,再贴出具体的错误。
      现将程序按照开始的时间进行一次排序,然后对排序后的数组进行一次迭代(far[i]),用一个now结构记录当前最长连续的开始时间和结束时间,如果far[i]的结束时间小于等于now的开始时间,那么now的开始时间不变,因为是排过续得了,但是结束时间就可能要更新了,如果far[i]的结束时间大于now的结束时间的话;如果far[i]的开始时间大于now的结束时间的话,那就是说这期间有一个没有人挤牛奶的时间,那就先判断now的开始时间到结束时间是否是最长的有人挤奶的时间,然后判断far[i]的开始时间和now的结束时间的差是否是最长无人挤奶的时间。
      错误如下:

      1、唯一一个不是快排实现的问题,在退出循环之后应该是还要判断一下now的时间是否是最长有人挤奶的时间。
      2、好久没写快排了,这一次写了快排的函数,但是竟然忘记递归调用自己了!有些吓人的错误。。
      3、我的快排的话,在元素个数在较少时直接调用插入排序,但是插入排序中间的第二层循环的条件写错了,把j>=s 写成了 j >=0。
      4,5、都是出现在选择枢纽元的函数里面,有一个确实错的很惨,可以这么表示:
                 if(a > b){
                   max = b;
                 }
      明显应该是max = a,这种错误,确实很惨,还有另外一个错误可以这么表示,有三个数a, b, c要求按顺序排序这三个数,我的错误的排序方法是:

    if(com(&a, &b) < 0){
    swap(a, b);
    }
    if(com(&b, &c) > 0){
    swap(b, c);
    }
    if(com(&a, &c) > 0){
    swap(a, c);
    }
      这样的话,如果a = 3, b = 2, c = 1,那么排序之后的结果是2, 1, 3而不是期望的1, 2, 3,原因很简单,因为最小的被放在了中间,而两边的却不是最小的,所以正确的方法应该是先把最小/最大的位置放对,然后再把剩下的一对比较放好就是:
    if(com(&a, &b) < 0){
    swap(a, b);
    }
    if(com(&a, &c) > 0){
    swap(a, c);
    }
    if(com(&b, &c) > 0){
    swap(b, c);
    }
      Ok了,把错误终结了,我就能够继续前进了,代码如下:
    /
    LANG: C
    ID: logoo2
    PROG: milk2
    /
    #include <stdio.h>
    #define max(a, b) ((a)>(b)?(a):(b))
    #define min(a, b) ((a)<(b)?(a):(b))
    #define swap(a, b) do{\
            struct far tmp;\
            tmp = a;\
            a = b;\
            b = tmp;\
    }while(0)
    struct far{
            int start, end;
    }far[5000];

    int com(struct far a, struct far b)
    {
            return a->start – b->start;
    }

    void insert_sort(int s, int t)
    {
            int i, j;
            struct far key;
            for(i = s + 1; i <= t; i++){
                    key = far[i];
                    /
                    mistack 3:
                      下面的j >= s 写成了 j >= 0
                    
    / 
                    for(j = i – 1; com(&key, &far[j]) < 0 && j >= s; j–){
                            far[j + 1] = far[j];
                    }
                    far[j + 1] = key;
            }
    }

    void choose(int s, int t)
    {
            int mid = (s + t) / 2;
    /
    mistack 5:
      下面比较的顺序原来是:
            if(com(&far[mid], &far[s]) < 0){
                    swap(far[mid], far[s]);
            }
            if(com(&far[mid], &far[t]) > 0){
                    swap(far[mid], far[t]);
            }
            if(com(&far[s], &far[t]) > 0){
                    swap(far[s], far[t]);
            }
      但是碰到, far[s] > far[mid] > far[t] 的情况就会出问题.. 
    /
            if(com(&far[mid], &far[s]) < 0){
                    swap(far[mid], far[s]);
            }
            if(com(&far[s], &far[t]) > 0){
                    swap(far[s], far[t]);
            }
            if(com(&far[mid], &far[t]) > 0){
                    /
                    mistack 4:
                      误把下面的far[t]写成了far[s]
                    
    /
                    swap(far[mid], far[t]);
            }
            swap(far[t – 1], far[mid]);
    }

    void sort(int s, int t)
    {
            int i, j;
            if(t – s < 9){
                    insert_sort(s, t);
                    return ;
            }
            choose(s, t);
            i = s, j = t – 1;
            while(i < j){
                    while(com(&far[++i], &far[t – 1]) < 0){
                            continue;
                    }
                    while(com(&far[–j], &far[t – 1]) > 0){
                            continue;
                    }
                    if(i < j){
                            swap(far[i], far[j]);
                    }
            }
            swap(far[t – 1], far[i]);
            /
            mistack 2:
              对快排的代码并不是特别的熟练,打完了上面的代码后忘记继续进行递归了。。 
            
    /
            sort(s, i – 1);
            sort(i + 1, t);
    }

    int main(void)
    {
            int n;
            int i;
            struct far now;
            int ans1 = 0, ans2 = 0;
            freopen("milk2.in", "r", stdin);
            freopen("milk2.out", "w", stdout);
            scanf("%d\n", &n);
            for(i = 0; i < n; i++){
                    scanf("%d%d", &far[i].start, &far[i].end);
            }
    //      qsort(far, n, sizeof(struct far), com);
            sort(0, n – 1);
            now = far[0];
            for(i = 1; i < n; i++){
                    if(far[i].start <= now.end){
                            now.end = max(now.end, far[i].end);
                    }else{
                            if(now.end – now.start > ans1){
                                    ans1 = now.end – now.start;
                            }
                            if(far[i].start – now.end > ans2){
                                    ans2 = far[i].start – now.end;
                            }
                            now = far[i];
                    }
            }
            /
            mistack 1:
              在退出循环时应该把最后剩下的数据进行判断. 
            
    /
            if(now.end – now.start > ans1){
                    ans1 = now.end – now.start;
            }
            printf("%d %d\n", ans1, ans2);
            return 0;
    }

  • USACO 1.1.4 Broken Necklace

      这一题以前我就有疑问,为什么代码一定是:

    a = b – w;
    b = w + 1;
      而不能是:
    a = b;
    b = 1;
      今天终于是把它给想通了,理由如下:
      这里之所以要写成a = b – w, b = w + 1 而不是a = b, b = 1 的原因我终于是找到了.原因如下:
      假设: 此时 b = 2, w = 1 则执行
      a = b, b = 1 之后的
      1.a = 2, b = 1
      而下一次就又进入这里,
      2.a = 1, b = 1
      但是不是有更好的分配方法么:

      1.a = b – w = 1, b = w + 1 = 2
      虽然和上面的和相同都是3, 但是对后面结果的影响不同了:
      2.a = b – w = 2 – 0 = 2, b = 1
      不久比上面的要好上1 ?  
      代码附上:
    /
    LANG:
    C

    ID: logoo2
    PROG:
    beads

    /
    #include
    <stdio.h>
    #include <string.h>

    char str[10001];

    int main(void)
    {
            int a = 0, b = 0, w = 0;
            char ch = ‘w’;
            int i,
    n;
            int ans = 0;
            freopen("beads.in", "r", stdin);
            freopen("beads.out", "w", stdout);
            scanf("%d\n", &n);
            scanf("%s",
    str);
            for(i = 0; i < n; i++){
                    str[i + n] =
    str[i];
            }
            str[i + n] = ‘\0’;
            for(i =
    0; i < 2  n &&
    ans < n; i++){
                    if(str[i]
    == ‘w’){
                            b++,
    w++;
                    }else if(str[i] != ch){
                            if(a + b >
    ans){
                                    ans = a +
    b;
                            }
                            /

                              这里之所以要写成a = b – w, b = w + 1
    而不是

                            a = b, b = 1
    的原因我终于是找到了.原因如下:

                            假设: 此时 b
    = 2, w = 1 则执行

                            a = b, b =
    1 之后的

                            1.a = 2, b =
    1

                            而下一次就又进入这里,
                            2.a = 1, b = 1
                            但是不是有更好的分配方法么:

                            1.a = b – w = 1, b = w + 1 =
    2

                            虽然和上面的和相同都是3,
    但是对后面结果的影响不同了:

                            2.a = b – w
    = 2 – 0 = 2, b = 1

                            不久比上面的要好上1 ?  
                            */
                            a = b –
    w;
                            b = w + 1;
                            w = 0;
                            ch =
    str[i];
                    }else{
                            b++, w = 0;
                    }
            }
            if(a + b > ans){
                    ans = a +
    b;
            }
            if(ans >
    n){
                    ans = n;
            }
            printf("%d\n", ans);
            return 0;
    }

  • USACO 1.1.3 Friday the Thirteenth

      这一个题目着实考察程序员的其他能力,时间方面我的能力真的很差,总是能把日期记错,把时间弄反,庆幸的是,我还是会看闹钟的,也不知道现在还有没有不会看的人,哈哈。
      代码实现如下:

    /
    LANG: C
    ID: logoo2
    PROG: friday
    /
    #include <stdio.h>
    int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int now = 6;
    int ans[7];

    int isry(int year)
    {
            return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
    }

    int main(void)
    {
            int n;
            int i, j;
            freopen("friday.in", "r", stdin);
            freopen("friday.out", "w", stdout);
            scanf("%d", &n);
            n += 1900 – 1;
            for(i = 1900; i <= n; i++){
                    if(isry(i)){
                            day[1] = 29;
                    }
                    for(j = 0; j < 12; j++){
                            ans[now]++;
                            now = (now + day[j]) % 7;
                    }
                    day[1] = 28;
            }
            printf("%d", ans[6]);
            for(i = 0; i < 6; i++){
                    printf(" %d", ans[i]);
            }
            printf("\n");
            return 0;
    }

  • USACO 1.1.2 Greedy Gift Givers

      这个题目唯一要注意的就是被除数不为0的问题,别的的话就是别太粗心就是,代码如下:

    /
    LANG: C
    ID: logoo2
    PROG: gift1
    /
    #include <stdio.h>
    #include <string.h>
    struct peo{
            char name[15];
            int get, give;
    }pep[10];
    int n;

    int getid(char str)
    {
            int i;
            for(i = 0; i < n; i++){
                    if(!strcmp(str, pep[i].name)){
                            return i;
                    }
            }
            return –1;
    }

    int main(void)
    {
            int i, j;
            char name[15], tmp[15];
            int t, s, m, av;
            freopen("gift1.in", "r", stdin);
            freopen("gift1.out", "w", stdout);
            scanf("%d\n", &n);
            for(i = 0; i < n; i++){
                    scanf("%s\n", pep[i].name);
            }
            while(scanf("%s\n", name) == 1){
                    t = getid(name);
                    scanf("%d%d\n", &m, &s);
                    if(s == 0){
                            av = 0;
                    }else{
                            av = m / s;
                    }
                    pep[t].get += m – av
    s;
                    pep[t].give = m;
                    for(i = 0; i < s; i++){
                            scanf("%s", tmp);
                            t = getid(tmp);
                            pep[t].get += av;
                    }
            }
            for(i = 0; i < n; i++){
                    printf("%s %d\n", pep[i].name, pep[i].get – pep[i].give);
            }
            return 0;
    }

  • USACO 1.1.1 Your Ride Is Here

      这一题的话,觉得我的代码函数独立的不错,因为题目毕竟简单,所以也就这么写吧:

    /
    LANG:C
    ID:zqynux2
    PROG: ride
    /
    #include <stdio.h>
    #include <string.h>
    typedef char string[7];

    int get_num(char ch)
    {
            return ch – ‘A’ + 1;
    }

    int change_to_num(string str, int n)
    {
            int i, sum = 1;
            int len;
            len = strlen(str);
            for(i = 0; i < len; i++){
                    sum *= get_num(str[i]);
                    sum %= n;
            }
            return sum;
    }

    int main(void)
    {
            int i, j;
            string team, star;
            freopen("ride.in", "r", stdin);
            freopen("ride.out", "w", stdout);
            scanf("%s%s", team, star);
            i = change_to_num(team, 47);
            j = change_to_num(star, 47);
            if(i == j){
                    printf("GO\n");
            }else{
                    printf("STAY\n");
            }
            return 0;
    }

  • Noip 2010 初赛

      来得比较晚,到考试的那个学校的时候,两点半开始比赛,两点钟才到。到处都是车子,大部分停的都是大巴和面包车,像我这种专车接来的不多呢!步入校门,一个门卫就迎上来,说把车停在那儿,手指了一下,顺着他指的方向我没看到啥空位,还是老师眼睛尖,找到了个最靠边的地方停下。
      下车就发现一栋硕大的教学楼,仔细一看才发现是两栋教学楼之间加了一个天桥,我们去报到的一路都是学生,不过听着既不是普通话也不是岳阳花,都是乡里话。结果一来就碰到不顺意的事,我的靠号上的名字不是我的名字,是张青,但是学生信息里面又是张青阳,那里的负责人看了下,后来说没事儿,估计会帮我解决掉吧。专门带了计算器,他们也不允许使用,交给老师保管了。
      老师之前就跟我说了,这里大部分都是外县人,不过没想到这么多,我找考场的时候,第一次找错了,找到另一个考场去,里面都是汨罗县的!后来找到了位置。
      考试开始了,发现题目挺简单的,一个月的复习还是简单有效的,除了个别题目……考场里还是有不少提前交卷的,最厉害的是我发现有一个交上去的时候反面完全是空的,根本没写。开始写的时候我又碰到不顺心的事,我想题目的时候总是东张西望,监考老师就以为我在作弊,跑下来检查了我的试卷和带的东西。

  • [转]对Chrome未来发展方向的一点猜想

    在使用Chrome半小时左右的时候,我就已经有了这样一个猜想。现在以文字的形式重新理清下思路吧,大概应该是这样的:

    其一,Google一贯以来的品牌形象是什么?应该是简洁、高效。不追求华丽,抛弃一切不实的功能,留下的都是核心的带来高效率的部分。现在的Chrome,虽然仅仅是第一个露面的版本,但简单的边栏和最大化的浏览窗口面积,已经昭示了这是一款秉承了Google一贯风格的作品;

    其二,Google为什么要推出浏览器产品?答案应该是整合。不是也在谋求推出操作系统么?老朽的微软,走的是一条从桌面整合网络应用的路,而年轻的Google正相反,它正在实践的,正是一条从网络服务整合向桌面的路。那么,循着这个整合的思路,未来的Chrome会巧妙的整合Google众多成名已久的网络服务,应该是必然的,也是必须的。

    好了,那么尝试着把上面两个思路合并一下,既要保持简洁,又要整合服务和扩充功能——Chrome的未来之路是什么样呢?关于这个问题,我从第一个版本的Chrome的书签栏得到了某种启示。要注意,Firefox非常有用的书签工具栏,在Chrome里被继承下来,但默认的情况下,它并不是附着在浏览器的边栏上,而是“浮动”在浏览窗口之内。

    是的,这就是我的结论,是我猜想未来Chrome的发展思路。如果说,Firefox的功能扩展,是通过插件的形式在菜单、边栏和侧栏中得到体现,那么,Chrome的功能扩展,将会是基于网络的,在浏览器窗口以内去展现!

    这不仅意味着Chrome外观将永远保持现在这样高度精简的风格,同时也意味着Google对于Chrome功能的扩展,将更加依托于网络,将更加体现桌面与网络的融合这一特征。

    也许,未来的Pisaca Web相册,仅当你使用Chrome访问的时候,会多浮现出一个工具条,实现快捷的上传、修改、命名等等功能;未来的Gmail,仅当你使用Chrome的时候,将可以像现在Firefox插件那样更换皮肤,新邮件提醒等等等等;还有未来的Chrome也许压根儿不会重视浏览器自身的订阅功能,而是直接切换到Greader,并巧妙的以某种方式使之与本地融合。

    对技术细节的构想,像我这样的凡人是很难把握的,但是,请记住我对Chrome发展思路的猜想:边栏将永远是简洁的,一切精彩,将在浏览窗口以内发生——只有如此,Chrome才可能与此前的众多Google产品一样,开创一个先河,引领一个时代……

  • Linux 内核中的巧妙 — 用宏定义函数

      在内核初始化的时候,调用的fork是一个用宏定义的函数,什么意思呢:
        static inline _syscall0(int,fork)
      这样就定义了一个函数int fork(void) ,至于
    _syscall0的代码,看下面:
    #define _syscall0(type,name) \
    type name(void) \
    { \
    long res; \
    asm volatile ("int $0x80" \
            : "=a" (
    res) \
            : "0" (_NR##name)); \
    if (res >= 0) \
            return (type)
    res; \
    errno = -__res; \
    return –1; \
    }

  • [转]docs.google.com 无法访问

    一、为什么不加密反而能访问?

    1、Google Docs经常用来传播非法信息

    Google Docs一直是不和谐信息的传播工具,因为它提供了https的访问方式,信息加密传输,第三者无法简单地窃听。Twitter上经常流传着一些使用Google Docs来传播的非法文档。

    前段时间网上流传着一份上海某大学的硕士论文,该论文揭示了非法软件FreeGate如何获取最新的代理列表,其中最为重要的一个渠道就是Google Docs,由于GDocs在中国大陆能被正常访问,FreeGate能实时更新DNS和代理列表,从而逃过封锁。FreeGate获取Google Docs里的文件信息同样使用https方式来访问。

    2、新型的拦截手段

    类似于Google Docs这样的,https无法访问、http方式却可以访问的屏蔽方式以往很少见。之所以采用这样的方式,原因有3:

    (1)Google Docs是一个常用的服务,不能完全屏蔽

    (2)Google有众多的IP,几乎不能完全屏蔽,如果完全屏蔽,则会影响Google的正常使用

    (3)必须要屏蔽Google Docs里的非法信息

    这3个原因推动了新的拦截手段的发展。根据猜测,这种手段是这样进行的:当客户端发出加密的DNS解析请求时,DNS监视端一旦发现这个请求是Google Docs的,立即发出一个重置信号。而对于一般的非加密DNS请求,DNS监视端则不工作,剩下的监视工作交由正常的审查系统来进行。

    3、新型拦截手段的好处

    (1)有效地阻止了Google Docs上非法信息的传播,又能让Google Docs正常使用

    (2)较为根本地封杀了FreeGate等非法软件

    (3)当用户放弃使用https方式而改用http方式来访问时,信息都是以明文传输,所有内容全部都进入到审查系统审查,非法信息又不能传播。

    二、解决方法一:OpenDNS

    既然https访问被重置是发生在向DNS发出请求的时候,一个能很容易就想到的解决方案是换一个不会审查DNS请求的DNS。OpenDNS是较为普遍的选择。使用方法很简单,将电脑的DNS设置为:

    208.67.222.222

    208.67.220.220

    如果你需要经常切换不同的DNS,可以使用“8个提高windows效率的免费软件”里介绍的NetSetman来进行DNS切换。

    但是,OpenDNS是位于国外的DNS,连接速度有点慢,我们不妨考虑另一种解决方案。

    三、解决方法二:自定义hosts (我用这种方法 )

    在hosts里添加Google Docs的解析IP直接绕过DNS查询,就能正常使用https的Google Docs了。

    hosts文件的位置:

    1、windows:C:\Windows\System32\drivers\etc\hosts

    2、Linux:/etc/hosts

    用记事本打开hosts文件,下面这些内容添加到hosts文件的顶部:

    209.85.225.101 docs.google.com

    74.125.127.100 writely.google.com

    74.125.127.139 spreadsheets.google.com

    保存hosts,重启浏览器后,https方式的Google Docs就能正常访问了。

    万一Gmail也遭遇到Google Docs的情况怎么办?用同样的方法,在hosts文件里加入Gmail的IP即可,为方便使用,我将提供有https方式的Google服务及其的IP列表如下:

    209.85.147.109 pop.gmail.com

    209.85.147.109 smtp.gmail.com

    66.102.7.19 mail.google.com

    209.85.225.101 docs.google.com

    209.85.225.102 groups.google.com

    74.125.127.139 spreadsheets.google.com

    74.125.127.100 services.google.com

    74.125.127.100 writely.google.com

    74.125.127.100 sites.google.com

    209.85.225.104 reader.google.com

    74.125.127.101 calendar.google.com

  • NOIp 2005 提高组 篝火晚会 解题报告

      这道题目我的思路很简单,就是模拟,然后每个人都只考虑自己旁边的,后来发现这种思路错了,写出来竟然是0分!!