HDU1216

跟素数筛法很像,主要是标记和识别(忽略)标记,直接两层for循环水过,也就171毫秒,不过要注意数组的大小,太大没必要,还占时间。

看某神的分类是“链表”。。。。。。开始就是看了分类定向思维用链表做,调BUG吐了口老血,然后实在不想调了,两层for就够了。。。。。。

但是如果数据量再大的话,for很容易超时,链表还是比较优化的算法,但是对于此数据量没必要。

#include <stdio.h>
#include <string.h>
#define N 33850    ///卡一卡大小,使用尽量少的空间,也减少扫描的区间

int a[33860];
int b[3010];

int main()
{
    int i, j, cou, cc, c;
    memset(a, 0, sizeof(a));   ///初始化标记数组
    cc = 0;
    for (i = 2; i <= N; i++) {
        if (!a[i]) {      ///找到排头的
            b[++cc] = i;    ///记录lucky number
            cou = i;
            c = 0;
            for (j = i; j <= N; j++) {
                if (!a[j] && i != j) {  ///注意第一次扫的时候不c++
                    c++;
                    if (c == cou) {
                        a[j] = 1;    ///标记,说明被派去刷碗,以后扫描时忽略ta
                        c = 0;   ///注意重置计数器
                    }
                }
            }
        }
    }

    int n;
    while (~scanf("%d", &n) && n) {
        printf("%d\n", b[n]);
    }
    return 0;
}

后来用链表提交的代码,跑了60多毫秒,内存耗得差不多快两倍,以前写链表习题的时候总是习惯性的把不用的节点free掉,但是想到OJ在申请的一瞬间已经达到最大内存空间了,再free就是给自己找事了。代码长度也没有差多少,还是觉得两层for比较好,其实也就是储存方式不一样,但是对数组比较好操作。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 33850

struct node {
    int num;
    struct node *next;
};

int sizen = sizeof(node);
int b[3010];

int main()
{
#if 0  ///
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif // 1
    node *head = NULL, *tail = NULL, *p = NULL;

    int i;
    for (i = 2; i <= N; i++) {              ///从2开始,创建链表
        p = (node *)malloc(sizen);

        p->num = i;
        p->next = NULL;

        if (head == NULL) {
            head = p;
            tail = head;
        } else {
            tail->next = p;
            tail = tail->next;
        }
    }

    int cou = 0, cc = 0;
    node *pre = NULL;
    for (p = head; p != NULL; head = head->next, p = head) {
        b[++cc] = p->num;   ///将第一个没有被派去刷碗的记录下来
        cou = p->num;     ///记录此人的编号,用于循环
        while (1) {
            for (i = 1; i <= cou; i++) {
                pre = p;
                p = p->next;
                if (p == NULL) break;    ///此处很重要,一个循环没跑完就到头了
            }
            if (p == NULL)  ///到头了跳出
                break;
            else {
                pre->next = p->next;   ///派去刷碗
                free(p);
                p = pre;   ///注意等于前一个
            }
        }
    }

    int n;
    while (~scanf("%d", &n) && n) {
        printf("%d\n", b[n]);
    }

    return 0;
}



你可能感兴趣的:(链表,数组,ACM,for循环,hduoj)