作者: yylogo

  • NOIP 2009 最优贸易 解题报告

      这题我纠结了三天,今天终于AC了,,辛苦死我了。。
      这题我看错了题目,连续两次。最后才弄清楚题目,就是两次搜索,第一次搜索所有的最小的价格,第二次搜索所有的最大的价格,然后就是枚举每一个节点的最大值-最小值。
      其中的数据结构是我偶然想到的,直接用一个数组表示,然后用另外一个数组进行标识每个都是哪个的邻接。
      思路真的没说清楚,我不想再说了,这题太难了(算法不难,空间压缩难。)。
    #include <stdio.h>
    #include <stdlib.h>
    #define MAX 100001
    #define minnum(a, b) ((a)<(b)?(a):(b))
    #define maxnum(a, b) ((a)>(b)?(a):(b))
    struct place{
            
    int x, y;
    }map[
    1000000];
    int inv[1000000], outv[1000000];
    /* 表示所有的的节点的入节点和出节点 */
    int len;
    int in[1000000], out[1000000];
    /* in[0] ~ in[1] 代表进节点1的的inv的下标. */
                    
    //上面的数组第一次都开小了, 
    int money[MAX];
    int max[MAX], min[MAX];
    int at[MAX];
    int n, m;
    int queue[MAX];
    int h, q;

    void enqueue(int x)
    {
            
    int t;
            t = q + 
    1;
            
    if(t > MAX){
                    t = 
    0;
            }
            
    if(t == h){
                    exit(-
    1);
            }
            queue[q] = x;
            q = t;
    }

    int exqueue(void)
    {
            
    int t, r;
            
    if(h == q){
                    exit(-
    1);
            }

            t = h + 1;
            
    if(t > MAX){
                    t = 
    0;
            }
            r = queue[h];
            h = t;
            
    return r;
            
    }

    void add(int i, int j)
    {
            map[len].x = i;
            map[len].y = j;
            in[j]++;
            out[i]++;
            len++;
    }

    int com1(const void *a, const void *b)
    {
            
    struct place i = *(struct place *)a, j = *(struct place *)b;
            
    return i.x – j.x;
    }

    int com2(const void *a, const void *b)
    {
            
    struct place i = *(struct place *)a, j = *(struct place *)b;
            
    return i.y – j.y;
    }

    void sort(int *a)
    {
            
    int t = 0, r;
            
    int i;
            
    for(i = 1; i <= n; i++){
                    r = a[i];
                    a[i] += t;
                    t += r;
            }
    }

    int main(void)
    {
            
    int i, j;
            
    int a, b, c;
            
    int t, ans;
            scanf(
    “%d%d“, &n, &m);
            
    for(i = 1; i <= n; i++){
                    scanf(
    “%d“, &money[i]);
            }
            
    for(i = 1; i <= m; i++){
                    scanf(
    “%d%d%d“, &a, &b, &c);
                    add(a, b);
                    
    if(c == 2){
                            add(b, a);
                    }
            }
            qsort(map, len, 
    sizeof(struct place), com1);           //对inv和outv赋值 
            
    for(i = 0; i < len; i++){
                    outv[i] = map[i].y;
            }
            qsort(map, len, 
    sizeof(struct place), com2);
            
    for(i = 0; i < len; i++){
                    inv[i] = map[i].x;
            }
            sort(in);                                               
    //对下标赋值 
            sort(out);

            for(i = 1; i <= n; i++){
                    min[i] = 
    1000000;
                    max[i] = 
    0;
            }

            enqueue(1); at[1] = 1;                         //搜索所有价格中最低的 
            
    while(h != q){
                    t = exqueue();
                    at[t] = 
    0;
                    
    for(i = out[t – 1]; i < out[t]; i++){
                            j = outv[i];
                            
    if(min[j] > min[t] || money[j] < min[j]){
                                    min[j] = minnum(money[j], min[t]);
                                    
    if(!at[j]){
                                            at[j] = 
    1;
                                            enqueue(j);
                                    }
                            }
                    }
            }
            enqueue(n); at[n] = 
    1;                         //搜索所有价格中最高的
            
    while(h != q){
                    t = exqueue();
                    at[t] = 
    0;
                    
    for(i = in[t – 1]; i < in[t]; i++){
                            j = inv[i];
                            
    if(max[j] < max[t] || money[j] > max[j]){
                                    max[j] = maxnum(money[j], max[t]);
                                    
    if(!at[j]){
                                            at[j] = 
    1;
                                            enqueue(j);
                                    }
                            }
                    }
            }

            ans = 0;
            
    for(i = 1; i <= n; i++){
                    
    if(max[i] – min[i] > ans){
                            ans = max[i] – min[i];
                    }
            }

            printf(“%d\n“, ans);
            
    return 0;
    }

  • Vim 设置(2)

      以后没看完Vim的用户手册一章就发一次上来(其实就是自己的笔记。)。

    set iskeyword&                   恢复iskeyword的默认值

     

    set map X xx                       让x映射为xx

    set compatible           兼容Vi的模式(建议不要兼容,既nocompatible)

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

    set backup                                    设置备份

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

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

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

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

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

    filetype plugin on      开启针对不同类型使用相应的plugin

    set nowrap                                    设置不要折行

    set sidescroll=x          设置每次移动出屏幕左右时移动的字符数..(貌似没讲清楚), 要求nowrap

    set whichwrap=…                Vim中多数移动光标的命令会在遇到行首或行尾时停止不动。可以通过这个控制具体可以设置哪些值可以通过help ‘whichwrap’查找.

    set list                                    可以让文件中的制表符成为可见的模式每个制表符会显示为^I, 每行末尾有$

    set listchars=…           可以修改list模式(上一条)下的制表符的样式

    set iskeyword=…                 这个选项定义了一个word中可以包含哪些字符. 要增加值的话直接set iskeyword += …, 去掉的话set iskeyword -= …

    set cmdheight=num           这个选项设置在Vim的最低下腾出几行来显示命令

      学到了第5章 定制你的Vim,感觉官方的help越来越有用了。(虽然是纯英文的,不过我还是能看懂十分之七,八)

  • 解决Ubuntu Gedit的乱码

      因为家里有两台机子,一台Linux一台Windows,而Linux那台的硬件配置差的要死,还有一些原因,我有时也用Windows看下电子书,坐下笔记,Windows下面的的docx(Word 2007的格式)能在Linux下打开,但是纯txt不能在我的Ubuntu下打开是乱码(这里说一下,在Fedora 的KDE(不知道它的Gnome行不行)里面的gedit能够智能识别编码。),到网上搜了一下,找到了解决方法,如下:

    缺省配置下,用 Ubuntu 的文本编辑器(gedit)打开 GB18030/GBK/GB2312 等类型的中文编码文本文件时,将会出现乱码。

    出现这种情况的原因是,gedit 使用一个编码匹配列表,只有在这个列表中的编码才会进行匹配,不在这个列表中的编码将显示为乱码。您要做的就是将 GB18030 加入这个匹配列表。

    • 命令行方式,适用于所有 Ubuntu 用户。

    复制以下命令到终端中,然后回车即可:

    gconftool-2 –set –type=list –list-type=string /apps/gedit-2/preferences/encodings/auto_detected “[UTF-8,CURRENT,GB18030,BIG5-HKSCS,UTF-16]”

    • 图形化方式,适用于 Ubuntu 用户,而不适用于 KUbuntu/XUbuntu 用户。

    您可以遵循以下步骤,使您的 gedit 正确显示中文编码文件。

    1. 按下 Alt-F2,打开“运行应用程序”对话框。
    2. 在文本框中键入“gconf-editor”,并按下回车键,打开“配置编辑器”。
    3. 展开左边的树节点,找到 /apps/gedit-2/preferences/encodings 节点并单击它。
    4. 双击右边的 auto_detected 键,打开“编辑键”对话框。
    5. 单击列表右边的“添加”按钮,输入“GB18030”,单击确定按钮。
    6. 列表的最底部新增加了一个“GB18030”。单击选中它,并单击右边的 “向上” 按钮直到 “GB18030” 位于列表的顶部为止。
    7. 单击确定按钮,关闭配置编辑器。

    现在,您的 gedit 应该能够顺利打开 GB18030 编码的文本文件了。

  • Ubuntu 10.04 桌面特效的设置

      早就听说过Linux下的桌面特效不比Windows 7逊色~! 而且内存和CPU需求量更小,记得以前我装Fedora 12的时候,使用桌面特效说没有显卡,后来有一张显卡可以给我用一阵子,特效好过瘾,但是后来显卡一拿走机子就开不开机了,因为特效太卡了~!结果只能重装系统(我那机子很老很老,已经是古董了,不过有我深深的回忆~!)
      现在用了Ubuntu,我是好了伤疤忘了疼,又想开特效,在菜单里面找到了特效的设置,有三种选项:无,一般,绚丽的(可能词语不对,反正就是这个意思),我先用了普通的,没什么特别的,就是鼠标,窗口下面多了点阴影,用绚丽的只有一个特色,就是移动窗口的时候,窗口变成了橡皮泥,弹赖弹去,玩着过瘾,后来到网上找了下,有这么一个软件:
    compizconfig-settings-manager可以使用更多的特效,我下载下来玩了下,确实过瘾,下载方式:
      在终端中输入:
    sudo apt-get install compizconfig-settings-manager
      后来我记得以前我看别人的Linux出现过火焰,而这个里面没有这个选项,我就又找啊找,找到了另外一个包:
      
    sudo apt-get install compiz-fusion-plugins-extra
      里面有更多的特效,什么3D的,火焰,还有各种各样有意思的特效~!~!
      而且关键是我那台破机子玩这些特效不会特别的卡(有一点还是很正常的,毕竟是老古董了。),后来我把3D的什么的都去掉了,只是在打开关闭放大放小的地方使用华丽的特效之后,就好很多了(3D还要让这机子的命啊~!)
      这里简单的记录一下,一呢给大家看看,二呢记录一下,让自己以后不到网上到处找两个软件包的名字。

  • NOIP2009 靶形数独 解题报告

      苦难的题目,我做着题只有一个想法:深搜,,暴力搜索!但是就连样例都超时了,我就直接找题解去了。
      网上找到一个题解,用位运算做的,大概看了下就开始仿造着写,去掉了感觉无用的功能(其实很有用),结果超时了。。。超时代码如下,75分。
    #include <stdio.h>
    #define getindex(t) ({\
            int i;\
            switch(t){\
            case 1:\
                    i = 0;\
                    break;\
            case 2:\
                    i = 1;\
                    break;\
            case 4:\
                    i = 2;\
                    break;\
            case 8:\
                    i = 3;\
                    break;\
            case 16:\
                    i = 4;\
                    break;\
            case 32:\
                    i = 5;\
                    break;\
            case 64:\
                    i = 6;\
                    break;\
            case 128:\
                    i = 7;\
                    break;\
            case 256:\
                    i = 8;\
                    break;\
            }\
            i;\
    })
    #define getboxid(i, j) ((3 * ((i) / 3)) + ((j) / 3))
    int rol[9],             //记录横排出现的数字
        col[9],             //记录竖排出现的数字
        box[9],             //记录九各宫出现的数字
        use[9];             //记录横排
    int ans = –1;
    //初始化为-1而不是0 
    int map[9][9];
    int mul[9][9] = {{6, 6, 6, 6, 6, 6, 6, 6, 6},
                     {6, 7, 7, 7, 7, 7, 7, 7, 6},
                     {6, 7, 8, 8, 8, 8, 8, 7, 6},
                     {6, 7, 8, 9, 9, 9, 8, 7, 6},
                     {6, 7, 8, 9,10, 9, 8, 7, 6},
                     {6, 7, 8, 9, 9, 9, 8, 7, 6},
                     {6, 7, 8, 8, 8, 8, 8, 7, 6},
                     {6, 7, 7, 7, 7, 7, 7, 7, 6},
                     {6, 6, 6, 6, 6, 6, 6, 6, 6}};

    void cal(void)
    {
            int i, j;
            int tmp = 0;
            for(i = 0; i < 9; i++){
                    for(j = 0; j < 9; j++){
                            tmp += map[i][j] * mul[i][j];
                    }
            }
            if(tmp > ans){
                    ans = tmp;
            }
    }

    void srch(int i)
    {
            int j, x, y;
            int pos, p;
            if(i == 9){
                    cal();
                    return ;
            }
            x = 511 ^ use[i];
            if(x == 0){
                    srch(i + 1);
                    return;
                    //掉了return  
            }
            y = x & -x;
            use[i] |= y;
            j = getindex(y);
            pos = 511 ^ (rol[i]|col[j]|box[getboxid(i, j)]);
            while(pos > 0){
                    p = pos & -pos;
                    pos ^= p;
                    map[i][j] = getindex(p) + 1;
                    rol[i] |= p;
                    col[j] |= p;
                    box[getboxid(i, j)] |= p;
                    srch(i);
                    rol[i] ^= p;
                    col[j] ^= p;
                    box[getboxid(i, j)] ^= p;
            }
            use[i] ^= y;
    }

    int main(void)
    {
            int i, j;
            int p;
            freopen(“abc.txt”, “r”, stdin);
            for(i = 0; i < 9; i++){
                    for(j = 0; j < 9; j++){
                            scanf(“%d“, &map[i][j]);
                            if(map[i][j] > 0){
                                    use[i] |= 1 << j;
                                    p = 1 << (map[i][j] – 1);
                                    if(((rol[i] & p)) || ((col[j] & p))
                                            || ((box[getboxid(i, j)] & p))){
                                            printf(“-1\n“);
                                            return 0;
                                    }
                                    rol[i] |= p;
                                    col[j] |= p;
                                    box[getboxid(i, j)] |= p;
                            }
                    }
            }
            srch(0);
            printf(“%d\n“, ans);
            return 0;
    }

      后来找了好久才想起来是把这个重要的剪枝去掉了(就是我认为不重要的部分。)
      修改代码如下:
    #include <stdio.h>
    #define getindex(t) ({\
            int i;\
            switch(t){\
            case 1:\
                    i = 0;\
                    break;\
            case 2:\
                    i = 1;\
                    break;\
            case 4:\
                    i = 2;\
                    break;\
            case 8:\
                    i = 3;\
                    break;\
            case 16:\
                    i = 4;\
                    break;\
            case 32:\
                    i = 5;\
                    break;\
            case 64:\
                    i = 6;\
                    break;\
            case 128:\
                    i = 7;\
                    break;\
            case 256:\
                    i = 8;\
                    break;\
            }\
            i;\
    })
    #define getboxid(i, j) ((3 * ((i) / 3)) + ((j) / 3))
    int rol[9],             //记录横排出现的数字
        col[9],             //记录竖排出现的数字
        box[9],             //记录九各宫出现的数字
        use[9];             //记录横排
    int count[9];           //每行值为0的个数
    int hk[9];              //按照这里的顺序进行深搜!! 重要剪枝
    int ans = –1;
    //初始化为-1而不是0 
    int map[9][9];
    int mul[9][9] = {{6, 6, 6, 6, 6, 6, 6, 6, 6},
                     {6, 7, 7, 7, 7, 7, 7, 7, 6},
                     {6, 7, 8, 8, 8, 8, 8, 7, 6},
                     {6, 7, 8, 9, 9, 9, 8, 7, 6},
                     {6, 7, 8, 9,10, 9, 8, 7, 6},
                     {6, 7, 8, 9, 9, 9, 8, 7, 6},
                     {6, 7, 8, 8, 8, 8, 8, 7, 6},
                     {6, 7, 7, 7, 7, 7, 7, 7, 6},
                     {6, 6, 6, 6, 6, 6, 6, 6, 6}};

    void cal(void)
    {
            int i, j;
            int tmp = 0;
            for(i = 0; i < 9; i++){
                    for(j = 0; j < 9; j++){
                            tmp += map[i][j] * mul[i][j];
                    }
            }
            if(tmp > ans){
                    ans = tmp;
            }
    }

    void srch(int t)
    {
            int i, j, x, y;
            int pos, p;
            if(t == 9){
            //这里是t不是i 
                    cal();
                    return ;
            }
            i = hk[t];
            x = 511 ^ use[i];
            if(x == 0){
                    srch(t + 1);
                    return;
                    //掉了return  
            }
            y = x & -x;
            use[i] |= y;
            j = getindex(y);
            pos = 511 ^ (rol[i]|col[j]|box[getboxid(i, j)]);
            while(pos > 0){
                    p = pos & -pos;
                    pos ^= p;
                    map[i][j] = getindex(p) + 1;
                    rol[i] |= p;
                    col[j] |= p;
                    box[getboxid(i, j)] |= p;
                    srch(t);
                    rol[i] ^= p;
                    col[j] ^= p;
                    box[getboxid(i, j)] ^= p;
            }
            use[i] ^= y;
    }

    int main(void)
    {
            int i, j;
            int p;

            for(i = 0; i < 9; i++){
                    for(j = 0; j < 9; j++){
                            scanf(“%d“, &map[i][j]);
                            if(map[i][j] > 0){
                                    use[i] |= 1 << j;
                                    p = 1 << (map[i][j] – 1);
                                    if(((rol[i] & p)) || ((col[j] & p))
                                            || ((box[getboxid(i, j)] & p))){
                                            printf(“-1\n“);
                                            return 0;
                                    }
                                    rol[i] |= p;
                                    col[j] |= p;
                                    box[getboxid(i, j)] |= p;
                            }else{
                                    count[i]++;
                            }
                    }
            }
            for(i = 0; i < 9; i++){
                    hk[i] = i;
            }

            for(i = 1; i < 9; i++){
                    p = hk[i];
                    for(j = i – 1; j >= 0 && count[hk[j]] > count[p]; j–){
                            hk[j + 1] = hk[j];
                    }
                    hk[j + 1] = p;
            }
            srch(0);
            printf(“%d\n“, ans);
            return 0;
    }
  • NOIP2009 Hankson的趣味题 解题报告

    Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫Hankson。现在,刚刚放学回家的Hankson 正在思考一个有趣的问题。
    今天在课堂上,老师讲解了如何求两个正整数c1 和c2 的最大公约数和最小公倍数。现在Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整数x 满足:
    1. x 和a0 的最大公约数是a1;
    2. x 和b0 的最小公倍数是b1。
    Hankson 的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的x 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x 的个数。请你帮助他编程求解这个问题。

    第一行为一个正整数n,表示有n 组输入数据。接下来的n 行每行一组输入数据,为四个正整数a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证a0 能被a1 整除,b1 能被b0 整除。
    【数据范围】
    对于 50%的数据,保证有1≤a0,a1,b0,b1≤10000 且n≤100。
    对于 100%的数据,保证有1≤a0,a1,b0,b1≤2,000,000,000 且n≤2000。

    每组输入数据的输出结果占一行,为一个整数。
    对于每组数据:若不存在这样的 x,请输出0;
    【说明】
    第一组输入数据,x 可以是9、18、36、72、144、288,共有6 个。
    第二组输入数据,x 可以是48、1776,共有2 个。
    若存在这样的 x,请输出满足条件的x 的个数;

    ====================================华丽的分割线====================================

    题目如上,我一开始的思路是把所有a1的倍数都枚举一次,然后用b1作为上限。

    但是估计会超时,就没下手,网上查了一下,有人用我这个思路,50分!!!以后我还是有思路就尝试下吧。。
    后来看了另外的思路,任何数都能够表示成素数之和,如:5=5^1,, 6 = 2^13^1,, 8 = 2^3等等。
    然后是最大公倍数=2^min(x1, y1)
    3^min(x2, y2)……
    最小公倍数=2^max(x1, y1)
    3^max(x2, y2)*……
    代码等下写上来.

    代码如下:

    #include <math.h>
    #include <stdio.h>
    #include <string.h>
    #define bzero(a) memset(a, 0, sizeof(a))
    #define MAX 10000
    int prime[MAX], count[MAX], num[MAX];
    int tot, t;
    
    int hcf(int a, int b)
    {
     int t;
     while(b){
     t = b;
     b = a % t;
     a = t;
     }
     return a;
    }
    
    void dfs(int now, int sum)
    {
     int i, n;
     if(now == t){
     num[tot++] = sum;
     return ;
     }
     dfs(now + 1, sum);
     for(i = 0; i < count[now]; i++){
     sum *= prime[now];
     dfs(now + 1, sum);
     }
    }
    
    void work(int n)
    {
     int i = 2;
     int limit = sqrt(n);
     while(i <= limit){
     if(n % i == 0){
     prime[t] = i;
     count[t] = 0;
     do{
     count[t]++;
     n /= i;
     }while(n % i == 0);
     t++;
     limit = sqrt(n);
     }
     i++;
     }
     if(n != 1){
     prime[t] = n;
     count[t++] = 1;
     }
     dfs(0, 1);
    }
    
    int main(void)
    {
     int n;
     int a0, a1, b0, b1;
     int i, j;
     int ans;
     scanf(%d, &n);
     for(i = 0; i < n; i++){
     scanf(%d%d%d%d, &a0, &a1, &b0, &b1);
     bzero(num);
     bzero(count);
     bzero(prime);
     tot = t = 0;
     work(b1);
     ans = 0;
     for(j = 0; j < tot; j++){
     // 这里的变量我用的都是i...+_^
     if((hcf(num[j], a0) == a1) &&
     ((num[j] / hcf(num[j], b0) * b0) == b1)){
     //必须写成上面这样, 而不是 num[j] * b0 / hcf(num[j], b0).
     //找了我两个多小时, 原来是先相乘的话会超过int的范围, 
     //而先除的话就不会超范围了 
     ans++;
     }
     }
     printf(%d\\n, ans);
     }
     return 0;
    }
     忽然想到了剪枝地方法,直接寻找所有与b0的最小公倍数是b1的数字,代码如下:
    #include <math.h>
    #include <stdio.h>
    #include <string.h>
    #define bzero(a) memset(a, 0, sizeof(a))
    #define MAX 10000
    int prime[MAX], count[MAX], num[MAX];
    int tot, t;
    int a0, a1, b0, b1;
    
    int hcf(int a, int b)
    {
     int t;
     while(b){
     t = b;
     b = a % t;
     a = t;
     }
     return a;
    }
    
    void dfs(int now, int sum)
    {
     int i, n, r;
     if(now == t){
     num[tot++] = sum;
     return ;
     }
     n = 0;
     r = prime[now];
     while(b0 % (r) == 0 && n < count[now]){ //剪枝, 使程序更上一层楼
     //这里直接寻找和b0的公约数是b1的数字 
     r *= prime[now];
     n++;
     }
     if(n < count[now]){
     while(n + 1 < count[now]){
     r *= prime[now];
     n++;
     }
     dfs(now + 1, sum * r);
     return ;
     }
    
     dfs(now + 1, sum);
     for(i = 0; i < count[now]; i++){
     sum *= prime[now];
     dfs(now + 1, sum);
     }
    }
    
    void work(int n)
    {
     int i = 2;
     int limit = sqrt(n);
     while(i <= limit){
     if(n % i == 0){
     prime[t] = i;
     count[t] = 0;
     do{
     count[t]++;
     n /= i;
     }while(n % i == 0);
     t++;
     limit = sqrt(n);
     }
     i++;
     }
     if(n != 1){
     prime[t] = n;
     count[t++] = 1;
     }
     dfs(0, 1);
    }
    
    int main(void)
    {
     int n;
     int i, j;
     int ans;
     scanf(%d, &n);
     for(i = 0; i < n; i++){
     scanf(%d%d%d%d, &a0, &a1, &b0, &b1);
     bzero(num);
     bzero(count);
     bzero(prime);
     tot = t = 0;
     work(b1);
     ans = 0;
     for(j = 0; j < tot; j++){
     // 这里的变量我用的都是i...+_^
    /* if((hcf(num[j], a0) == a1) &&
     ((num[j] / hcf(num[j], b0) * b0) == b1)){*/
     //必须写成上面这样, 而不是 num[j] * b0 / hcf(num[j], b0).
     //找了我两个多小时, 原来是先相乘的话会超过int的范围, 
     //而先除的话就不会超范围了
    
     //当程序优化之后上面的判断就变成了下面的判断:
     if(hcf(num[j], a0) == a1){
     ans++;
     }
     }
     printf(%d\\n, ans);
     }
     return 0;
    }

    忽然又想到了一些剪枝,我还尝试一下。

  • NOIP2009 潜伏者 解题报告

    今天把NOIP 2009的所有题目做了一遍,当做考试来做,结果只做出了这一题,而且还只有90分。。死心了。。
    代码如下:

    /*要注意:
     * 1.\'A\'-\'Z\'扫描完毕就停止, (不管内容还有没有~!)
     * 2,长度小于26就Failed
     * 3,二者是一一对应的关系
     * 4,输入的字符串是密子, 不是原信息
     */
    #include <stdio.h>
    **char** map[26], mapp[26];
    **char** string[101];
    **char** start[101], end[101];
    
    **int** main(**void**)
    {
     **int** count = 0;
     **int** i;
     scanf(%s, end); //输入的时候写成了%s\\n,,
     scanf(%s, start);
     scanf(%s, string);
     i = 0;
     **while**(count < 26 && end[i] != \'\\0\'){
     **if**(((map[end[i] - \'A\'] > 0) && (map[end[i] - \'A\'] != start[i])) ||
     ((mapp[start[i] - \'A\'] > 0) && (map[start[i] - \'A\'] != end[i]))){
     //两种数据是一一对应的~! 
     **break**;
     }
     **if**(map[end[i] - \'A\'] == 0){ //忘记给count递增了..
     map[end[i] - \'A\'] = start[i];
     mapp[start[i] - \'A\'] = end[i];
     //两种数据是一一对应的~!
     count++;
     }
     i++; //掉了i++
     //差点提交了, 要把i放在判断的外面才行
     }
     **if**(count != 26){
     printf(Failed\\n);
     **return** 0;
     }
     i = 0; //忘记赋值了
     **while**(string[i] != \'\\0\'){
     putchar(map[string[i] - \'A\']);
     i++; //掉了i++
     }
     putchar(\'\\n\');
     **return** 0;
    }

    顺便提一下,上面的代码是使用Vim转换的!

  • 2010年08月09日

      承蒙高人指点,NOIP的希望终于感觉大点了!哈哈,争取今年拿省1=,不管距离远不远~
      慢慢加油吧~!

  • Vim 具名标记

    ma                                                           将当前光标的位置命名为a(可以是其他字符)

    `a                                                              跳转到标记a处

    ‘a                                                             跳转到标记a所在的行

    :marks                                                    显示标记列表

    `‘                                                               进行此次跳转之前的位置

    ‘”                                                              上次编辑文件时光标最后停留的位置

    ‘[                                                               最后一次修改的起始位置

    ‘]                                                               最后一次修改的结束位置

    “                                                               回到刚刚搜索到的地方

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

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

     

    上面的`”和Ctrl-O, Ctrl-I 的功能和别好用..

  • Vim 选择(Visual)模式

    V                                   进入行选取模式

    v                                   进入选取模式

    Ctrl+V                         进入块选择模式

    o                                   会让光标到选取文本的另一头

    O                                  会让光标在左右两个角移动