作者: yylogo

  • Vim 搜索

      搜索的一些功能:

    ?                                                              向前搜索

    /                                                                向后搜索

    *                                                               向后搜索光标所在的单词(单个单词,类似\<…\>)

    g*                                                            向后搜索光标所在的单词(允许内部包含, 类似….)

    #                                                               向前搜索光标所在的单词(单个单词,类似\<…\>)

    g#                                                             向前搜索光标所在的单词(允许内部包含, 类似….)

     

    the\>                                                       查找单词以the结尾的

    \<the                                                       查找单词以the开头的

    \<the\>                                                  查找单词the,包含the的不算,如:there

    ^xx                                                          匹配一行以xx开头的

    xx$                                                           匹配一行以xx结尾的

    c.m                                                          .这个字符可以匹配到任何字符,如c.m可以匹配com, cem

    .                                                              去掉.的特殊意思,使之变成字符’.’

    “                                                               回到刚刚搜索到的地方

    Ctrl-O                                                      回到早先停止光标的地方(大写O, 要按Shift)

    Ctrl-I(可用Tab代替)                        回到后来停止光标的地方(大写I, 要按Shift)

     

  • Vim 的设置

      在:命令下的一些设置,以后还会陆续添加的:

    compatible                                                               兼容Vi的模式(建议不要兼容)

    autoindent                                                               开始新行时与前一行缩进相同

    backup                                                                       设置备份

    history=x                                                                   设置冒号命令和搜索命令的历史列表的长度为x

    ruler                                                                                     总是在窗口的右下角显示当前光标行列信息

    showcmd                                                                 在右下角显示一个命令完整的部分(就是显示正常模式下的命令)

    showmode                                                               总是显示当前所在的模式

    incsearch                                                                 在输入要搜索的字符串的同时就开始搜索当前输入的这部分了

  • 中缀表达式转换后缀表达式

    能够把中缀表达式转换成后缀表达式,是在为http://www.rqnoj.cn/Problem_18.html 这一题做准备,感觉写的还不错,关键是在优先级的处理方面(compare函数),整个代码如下(包含驱动函数main):
    只支持+-*^()和变量

    #include <stdio.h>
    #include <ctype.h>
    #define MAX 101
    #define NUM 0
    #define CHAR 1
    #define OPER 2
    #define STR +-*^()
    const unsigned used = 100000000;
    #define bits 8
    struct t{
     unsigned num[MAX];
     char type[MAX];
     int len;
    }std;
    unsigned stack[50];
    int top;
    #define push(a) ({stack[top++] = a;})
    #define pop() ({stack[--top];})
    
    void add(struct t *to, unsigned key, char type)
    {
     to->num[to->len] = key;
     to->type[to->len] = type;
     to->len++;
    }
    
    int par[6][6] ={{-1, -1, 1, 1, 1, -1},
     {-1, -1, 1, 1, 1, -1},
     {-1, -1, -1, 1, 1, -1},
     {-1, -1, -1, -1, 1, -1},
     {1, 1, 1, 1, 1, 0},
     {-1, -1, -1, -1, 0, 1},};
    /*
     0:加法
     1:减法
     2:乘法
     3:求幂
     4:正括号
     5:反括号
    */
    
    int compare(int a, int b)
    {
     char *i, *j;
     i = strchr(STR, a);
     j = strchr(STR, b);
     a = i - STR;
     b = j - STR;
     return par[a][b];
    }
    
    void change(struct t *to, char *from)
    {
     int i, j;
     int ch;
     unsigned t;
     push(\'(\');
     for(i = 0; from[i] != \'\\0\'; i++){
     ch = from[i];
     if(strchr(STR, ch) != NULL){ /* 处理三种情况 */
     j = compare(stack[top - 1], ch);
     while(j < 0){
     add(to, pop(), CHAR);
     j = compare(stack[top - 1], ch);
     }
     if(j == 0){
     pop();
     }else{
     push(ch);
     }
     }else if(isdigit(ch)){
     t = 0;
     while(isdigit(from[i])){
     t *= 10;
     t += from[i++] - \'0\';
     }
     i--;
     add(to, t, NUM);
     }else if(ch == \'a\'){
     add(to, ch, OPER);
     }
     }
     while(top != 1){ /* 把最后几个符号去掉, 但是在函数
     开始加入的正括号不加入 */
     add(to, pop(), CHAR);
     }
    }
    
    int main(void)
    {
     int i;
     char tmp[51];
     scanf(%s, tmp);
     change(&std, tmp);
     for(i = 0; i < std.len; i++){
     if(i != 0){
     printf( );
     }
     switch(std.type[i]){
     case NUM:
     printf(%u, std.num[i]);
     break;
     case CHAR:
     printf(%c, std.num[i]);
     break;
     case OPER:
     printf(%c, std.num[i]);
     break;
     }
     }
     printf(\\n);
     return 0;
    }
  • 海贼王和火影忍者

      现在碰到的OI题目都太难了, 伤细胞, 想不出来, 写点无关的东西, 放松下.
      海贼王和火影忍者都是很好看的动画, 火影忍者前期真的很好看, 鸣人为了自己的理想, 改变了一个又一个人, 影响了周围的人, 但是到后期, 发展到现在越来越觉得无聊, 话说鸣人出去修行三年, 回来除了长高没见到什么成效(个别可能有点, 继续向下看.), 但是如今仙人模式, 收复九尾, 你就这么的神奇? 半个小时就把那么厉害的九尾给KO了, 吸收了?? 还什么九尾是最厉害的尾兽哦, 现在的越看越无聊, 尽扯一些恶心的要死和做作剧情, 总是十分明了的把感情讲出来..
      而海贼王则是越来越好看, 从一开始作者就埋下了无数的伏笔, 剧情也都是十分紧凑的, 那个世纪里面的逻辑也十分完整, 不想火影忍者, 一个什么都不会的下忍看了半个小时的卷轴就能打败上忍了.. 而且海贼王里面我最欣赏的是他们之间的团队配合, 索隆说过, 真正的团队配合就是只要把自己分内的事做好了这就是一个强大的集体. 我最喜欢的是海贼王里面路飞海贼团里每个人都有一些身份, 背景, 理想. 不想火影忍者, 整个一故事围绕着鸣人写, 别人就没理想, 没青春了. 海贼王里面人人都有理想, 而且不是一样的, 路飞-海贼王, 索隆-世界第一的剑客, 香吉士-找到All Bule海洋……
      不过海贼王里面最让我为之呐喊的是他们能真正变强大, 不想火影忍者修行两天就可以厉害很多了, 那空闲时间他怎么不修行.. 别说什么时机没到, 那是玩笑. 海贼王里面路飞一伙变强大的唯一方式就是战斗, 和比自己强大的人战斗, 为了伙伴, 为了理想, 不能够倒下, 不然伙伴会死, 理想会破灭, 所以能做的只有两件事, 第一战败, 第二就是打倒站在面前的每一个人! 让自己比他强大, 自己才能保护好自己的伙伴和理想.
      哎,, 希望自己能变成和路飞他们一样, 每做一道题目, 都能够收获一些对自己大有益处的思想, 细节等.
      哎, 不写了, 继续想题目去.

  • USACO 3.3-1 Riding the Fences骑马修栅栏

    欧拉回路,我知道怎么做,但是我不知到为什么可以这么做!,囧囧;就当是背课文把,反正这就是欧拉回路。
    如果有节点的度为奇数就从它开始,否则就从最小的开始,然后就是看下面的代码把:

     #include <stdio.h>
    #define MAXV 500
    #define MAXE 1024
    char map[MAXV][MAXV];
    int path[MAXE];
    int degree[MAXV];
    int len;
    int max;
    
    void add(int a, int b)
    {
     map[a][b]++, degree[a]++;
    }
    
    void delete(int a, int b)
    {
     map[a][b]--, degree[b]--;
    }
    
    int getneighbor(int a)
    {
     int i;
     for(i = 0; degree[a] != 0; i++){
     if(map[i][a]){
     return i;
     }
     }
    }
    
    void fence(int now)
    {
     int i;
     while(degree[now]){
     i = getneighbor(now);
     delete(i, now);
     delete(now, i);
     fence(i);
     }
     path[len++] = now;
    }
    
    int main(void)
    {
     int i;
     int n, k = 501;
     int a, b;
     freopen(fence.in, r, stdin);
     freopen(fence.out, w, stdout);
     scanf(%d, &n);
     for(i = 0; i < n; i++){
     scanf(%d%d, &a, &b);
     a--, b--;
     add(a, b);
     add(b, a);
     if(max < a){
     max = a;
     }
     if(max < b){
     max = b;
     }
     if(k > a){
     k = a;
     }
     if(k > b){
     k = b;
     }
     }
     for(i = 0; i <= max; i++){
     if(degree[i] & 1){
     k = i;
     break;
     }
     }
     fence(k);
     for(i = len - 1; i >= 0; i--){
     printf(%d\\n, path[i] + 1);
     }
     return 0;
    }
  • 算法导论 习题之插入排序从大到小

    插入排序其实很好理解,就是保证前i – 1个都是排好序了的,再排第i个,下面这个是从大到小排序的:

    
    /* 从大到小的插入排序 */
    void insert_sort(int a[], int n)
    {
     int i, j;
     int key;
     for(i = 1; i < n; i++){
     key = a[i];
     for(j = i - 1; (j >= 0) && (key > a[j]); j--){
     a[j + 1] = a[j];
     }
     a[j + 1] = key;
     }
    }
    
    /* 驱动程序如下 */
    int main(void)
    {
     int a[10];
     int i;
     for(i = 0; i < 10; i++){
     scanf(%d, &a[i]);
     }
     insert_sort(a, 10);
     for(i = 0; i < 10; i++){
     printf(%d , a[i]);
     }
     return 0;
    }
  • Vim 和 Emacs, 我的选择

      既然是一个程序员就要像一个程序员,总需要有一款顺手,熟练地软件让自己使用吧,说到软件,编译和调试方面gcc和gdb无可替代,但是在编辑方面,有两把等待我霸气的剑,每一把身上都是波光粼粼,荣誉陪伴着的!我不知道选哪个——vim, emacs,其实我用vim有一阵子了,但是我还是不够熟练,所以现在换的话还算来得及。
      到网上搜了好久,最后两篇帖子给了我决定,一篇是一个人从vim转到emacs里去的文章,他说他学Vim很久了,后来却爱上了Emacs。他说他如果没有.emacs那Vim和Emacs是差不多的,但是他有了之后Emacs就一定比Vim好!呵呵,我觉得可笑。在下面评论的一个人也觉得可笑,既然是比较,那就要公平,什么叫做公平,就是在相同的物质基础上进行比较,这个人使用了.emacs,而vim就是原装的,你这叫公平?你这叫Emacs强大,我不是说Emacs不强大,只是说这个人不该从这个角度去说明。
      另外一篇文章是比较客观的比较这两把剑,其中一句话让我咬定不学它了。大概是说Vim是适合写程序,打代码,Emacs则更加强大,几乎什么功能都有,包括收发邮件等。。
      我不再看别的了,收发邮件谁要啊?以后我也不摇动意识了,就学Vim!

  • NOIP2005 循环 解题报告

    刚看到题目,我不知所措,真不知道怎么做(NOIP我真的是太菜了。)。
    到网上找到了一个高手的结题报告(几个题目我都是搜到的他的。),原来可以用DP来解大致的思路是这样子的:
    比如这里有一个循环(只是假设,可能没有这个数):123 245 344 123,这就是一个循环数,没错吧?,好,再仔细观察一下,第一项和最后一项的后二位数也是相同的,也就是说后k个数循环的长度是后k-1个数循环长度的倍数。
    恩,至于代码的话,等下再发上来

    (2010年8月4日18:26:10),这一题希望能成为我的OI转折题,没什么别的,这题我吃了不少亏,总结了几条教训,如下:
    1、拿到题目先仔细分析,是否拥有子问题。
    上面这一点不只是DP,各种算法都是大事化小,小事化了,不说用什么出众的数学,但是分析题目的时候,没有别的,要理性,争取能够找到更小的问题,然后逐一攻破。
    2、不要为了一些微不足道剪纸而丧失了程序的正确性。
    总是认为程序的效率很重要,要多用什么位运算,一些小型剪枝。以后的话尽量不要用这些运算,因为Noip只是要确保在规定时间内完成程序,所以100ms和10ms对于成绩来说都是一样的。
    3、暂时就说这么多吧。
    当然,程序AC之后还是可以适当的优化一下,体验速度给我带来的快乐!
    题目的代码如下,可读性自我感觉4颗星!

    
    #include <stdio.h>
    #include <string.h>
    #define max(a, b) ((a)>(b)?(a):(b))
    #define read(a) read_(&a)
    #define output(a) output_(&a)
    #define mul(a, b) mul_(&a, &b)
    #define mulnum(a, b) mulnum_(&a, b)
    #define copy(a, b) memcpy((a), (b), sizeof(numtype) * ((b)->len) + sizeof(int))
    #define give(a, b) give_(&a, b)
    #define getnum(a, i) (a.num[i])
    #define MAX 201
    const int used = 10;
    typedef char numtype;
    typedef struct bignum{
     int len;
     numtype num[MAX];
    }bignum;
    bignum std, x, num, num1, ans;
    int k;
    
    void read_(bignum *a)
    {
     char tmp[101];
     int i;
     scanf(%s, tmp);
     a->len = strlen(tmp);
     i = a->len - 1;
     while(i >= 0){
     a->num[i] = tmp[a->len - 1 - i] - \'0\';
     i--;
     }
    }
    
    void output_(bignum *a)
    {
     int i;
     numtype *num = a->num;
     for(i = a->len - 1; i >= 0; i--){
     printf(%d, num[i]);
     }
     printf(\\n);
    }
    
    void give_(bignum *a, int n)
    {
     int i;
     for(i = 0; n != 0; i++){
     a->num[i] = n % used;
     n /= used;
     }
     a->len = i;
    }
    
    void mul_(bignum *a, bignum *b)
    {
     static bignum tmp;
     int len = a->len + b->len - 1;
     int i, j;
     numtype re;
     memset(&tmp, 0, sizeof(bignum));
     /* 上面这段代码我错了一次二次三次.. 我最后才知道所有的问题都是它... */
     for(i = 0; i < a->len; i++){
     re = 0;
     for(j = 0; j < b->len; j++){
     tmp.num[i + j] += a->num[i] * b->num[j] + re;
     //是+=
     re = tmp.num[i + j] / used;
     if(re > 0){
     tmp.num[i + j] %= used;
     }
     }
     if(re > 0){
     tmp.num[i + j] = re;
     len = max(i + j + 1, len);
     }
     }
     if(len > k){
     len = k;
     }
     tmp.len = len;
     copy(a, &tmp);
    }
    
    void mulnum_(bignum *a, int n)
    {
     int i;
     numtype re = 0;
     /* 忘记初始化 */
     for(i = 0; i < a->len; i++){
     a->num[i] = a->num[i] * n + re;
     re = a->num[i] / used;
     if(re > 0){
     a->num[i] %= used;
     }
     }
     if(re > 0){
     a->num[i] = re;
     a->len++;
     } 
    }
    
    int main(void)
    {
     int i, j;
     int a, b;
     read(std);
     give(ans, 1);
     copy(&x, &std);
     give(ans, 1);
     scanf(%d, &k);
     for(i = 0; i < k; i++){
     copy(&num, &std);
     give(num1, 1);
     b = getnum(std, i);
     for(j = 1; j <= 10; j++){
     mul(num1, x);
     mul(num, x);
     a = getnum(num, i);
     if(a == b){
     copy(&x, &num1);
    /* give(t, j);
     mul(ans, t);*/
     mulnum(ans, j);
     break;
     }
     }
     if(j > 10){
     printf(-1\\n);
     return 0;
     }
     }
     output(ans);
     return 0;
    }
  • Glibc 中的 qsort

    这函数真够长的,吓死!
    记得我前两天看到别人做的一个程序,用的是自己写的快速排序,而我用的qosrt,结果我的100ms,他的350ms。这程序真贼快的
    因为我把每天的倾城都安排好了,所以只有半个小时的时间看,所以没看完,先注释一部分吧,明天再补一部分,估计一下子还看不完。整个qsort的代码如下:

    
    #include <alloca.h>
    #include <limits.h>
    #include <stdlib.h>
    #include <string.h>
    
    /* 交换一块内存数据, 长度为size字节 */
    #define SWAP(a, b, size) \\
     do \\
     { \\
     register size_t __size = (size); \\
     register char *__a = (a), *__b = (b); \\
     do \\
     { \\
     char __tmp = *__a; \\
     *__a++ = *__b; \\
     *__b++ = __tmp; \\
     } while (--__size > 0); \\
     } while (0)
    
    #define MAX_THRESH 4
    
    typedef struct{
     char *lo;
     char *hi;
    }stack_node;
    /* 初步猜测lo和hi,的功能,根据下面的PUSH和POP宏, 估计是一段内存的两端
     lo就是low, hi就是high,就是说从low所指向的位置到hi所指向的位置就是
     这个元素的内容。 */
    
    #define STACK_SIZE (CHAR_BIT * sizeof(size_t))
     /* 关于这个CHAR_BIT在网上搜了下,在limits.h文件中有定义:
     #define CHAR_BIT 8 */
    #define PUSH(low, high) ((void)((top->lo = (low)), (top->hi = (high)), ++top))
    #define POP(low, high) ((void)(--top, (low = top->lo), (high = top->hi)))
     /* 译(准确的说是注释的人:zqynux/My S-K-Y)者感到有点奇怪,
     能转换void这个类型 */
    #define STACK_NOT_EMPTY (stack < top)
    /* 上面三个都是超快速 + 简单的栈操作 */
    
    void _quicksort (void *const pbase, size_t total_elems, size_t size,
     __compar_d_fn_t cmp, void *arg)
     /* 其实__compar_d_fn_t这个类型我没查也知道是什么类型, 就是一个函数指针,
     所以就没查了. */
    {
     register char *base_ptr = (char *) pbase;
     const size_t max_thresh = MAX_THRESH * size;
    
     if(total_elems == 0)
     /* Avoid lossage with unsigned arithmetic below. */
     return;
    
     if(total_elems > MAX_THRESH){
     char *lo = base_ptr;
     char *hi = &lo[size * (total_elems - 1)];
     stack_node stack[STACK_SIZE];
     stack_node *top = stack;
    
     PUSH (NULL, NULL);
    
     while (STACK_NOT_EMPTY){
     char *left_ptr;
     char *right_ptr;
    
     /* Select median value from among LO, MID, and HI. Rearrange
     LO and HI so the three values are sorted. This lowers the
     probability of picking a pathological pivot value and
     skips a comparison for both the LEFT_PTR and RIGHT_PTR in
     the while loops. */
    
     char *mid = lo + size * ((hi - lo) / size >> 1);
    
     if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
     SWAP (mid, lo, size);
     if ((*cmp) ((void *) hi, (void *) mid, arg) < 0)
     SWAP (mid, hi, size);
     else
     goto jump_over;
     if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
     SWAP (mid, lo, size);
    jump_over: ;
    
     left_ptr = lo + size;
     right_ptr = hi - size;
    
     /* Here\'s the famous ``collapse the walls\'\' section of quicksort.
     Gotta like those tight inner loops! They are the main reason
     that this algorithm runs much faster than others. */
     do{
     while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
     left_ptr += size;
    
     while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
     right_ptr -= size;
    
     if (left_ptr < right_ptr){
     SWAP (left_ptr, right_ptr, size);
     if (mid == left_ptr)
     mid = right_ptr;
     else if (mid == right_ptr)
     mid = left_ptr;
     left_ptr += size;
     right_ptr -= size;
     }else if (left_ptr == right_ptr){
     left_ptr += size;
     right_ptr -= size;
     break;
     }
     }while (left_ptr <= right_ptr);
    
     /* Set up pointers for next iteration. First determine whether
     left and right partitions are below the threshold size. If so,
     ignore one or both. Otherwise, push the larger partition\'s
     bounds on the stack and continue sorting the smaller one. */
    
     if ((size_t) (right_ptr - lo) <= max_thresh){
     if ((size_t) (hi - left_ptr) <= max_thresh)
     /* Ignore both small partitions. */
     POP (lo, hi);
     else
     /* Ignore small left partition. */
     lo = left_ptr;
     }else if ((size_t) (hi - left_ptr) <= max_thresh)
     /* Ignore small right partition. */
     hi = right_ptr;
     else if ((right_ptr - lo) > (hi - left_ptr)){
     /* Push larger left partition indices. */
     PUSH (lo, right_ptr);
     lo = left_ptr;
     }else{
     /* Push larger right partition indices. */
     PUSH (left_ptr, hi);
     hi = right_ptr;
     }
     }
     }
    
     /* Once the BASE_PTR array is partially sorted by quicksort the rest
     is completely sorted using insertion sort, since this is efficient
     for partitions below MAX_THRESH size. BASE_PTR points to the beginning
     of the array to sort, and END_PTR points at the very last element in
     the array (*not* one beyond it!). */
    
    #define min(x, y) ((x) < (y) ? (x) : (y))
    
     {
     char *const end_ptr = &base_ptr[size * (total_elems - 1)];
     char *tmp_ptr = base_ptr;
     char *thresh = min(end_ptr, base_ptr + max_thresh);
     register char *run_ptr;
    
     /* Find smallest element in first threshold and place it at the
     array\'s beginning. This is the smallest array element,
     and the operation speeds up insertion sort\'s inner loop. */
    
     for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
     if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
     tmp_ptr = run_ptr;
    
     if (tmp_ptr != base_ptr)
     SWAP (tmp_ptr, base_ptr, size);
    
     /* Insertion sort, running from left-hand-side up to right-hand-side. */
    
     run_ptr = base_ptr + size;
     while ((run_ptr += size) <= end_ptr){
     tmp_ptr = run_ptr - size;
     while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
     tmp_ptr -= size;
    
     tmp_ptr += size;
     if (tmp_ptr != run_ptr){
     char *trav;
    
     trav = run_ptr + size;
     while (--trav >= run_ptr){
     char c = *trav;
     char *hi, *lo;
    
     for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
     *hi = *lo;
     *hi = c;
     }
     }
     }
     }
    }
  • NOIP 过河 解题报告

    这题我不怎么说吧,我在网上搜的,到现在为止为什么能这样我还是没想通,只知道这样能过。
    就当是个定理吧,记住就是了,这题我不太想解释,看代码吧:

    #include <stdio.h>
    #define INT_MAX 200000000
    int stone[100];
    int map[9190], f[9190];
    
    int com(const void *a, const void *b){ return *(int *)a - *(int *)b; }
    
    int main(void)
    {
     int i, j, k;
     int l, s, t, n;
     int p, jmp = 0;
     int ans = 0;
    
     scanf(%d%d%d%d, &l, &s, &t, &n);
     for(i = 0; i <= 9190; i++){
     f[i] = INT_MAX;
     }
     f[0] = 0;
     for(i = 0; i < n; i++){
     scanf(%d, &stone[i]);
     }
     if(s == t){
     for(i = 0; i < n; i++){
     if(stone[i] % s == 0){
     ans++;
     }
     }
     printf(%d\\n, ans);
     return 0;
     }
     qsort(stone, n, sizeof(int), com);
     k = 0;
     for(i = 0; i < n; i++){
     p = stone[i] - k - 1;
     if(p >= s * t){
     jmp += p - s * t;
     }
     map[stone[i] - jmp] = 1;
     k = stone[i];
     }
     if(l - k > s*t){
     jmp += l - k - s*t;
     }
     l -= jmp;
     for(i = 0; i <= l; i++){
     if(f[i] == INT_MAX){
     continue;
     }
     for(j = s; j <= t; j++){
     if(f[i + j] > f[i] + map[i + j]){
     f[i + j] = f[i] + map[i + j];
     }
     }
     }
     for(i = l, ans = INT_MAX; i <= l + t - 1; i++){
     if(ans > f[i]){
     ans = f[i];
     }
     }
     printf(%d\\n, ans);
    
     return 0;
    }