zoukankan      html  css  js  c++  java
  • SGU 108 Selfnumbers 2

    SGU_108

        这个题目可以直接筛出来结果,但要注意几个问题:①数组不够大,但由于推断的时候前后影响的区间并不大,因此我们可以把数组循环使用,对数组操作的时候多加一个取模运算即可。②空间不允许我们先把所有结果都处理出来,因此我们可以在筛的过程中,标记一下当前筛出的是第几个数,如果是需要输出的,再存到指定位置去即可,这样只要开出K的空间来就可以了。③由于si可能是无序的,而我们在筛的过程中只能顺序找到,而我们又不能每次都花O(K)的时间去看看当前是不是要输出的,所以需要预先按si的值排下序,为了能够方便查找、更改,我们不能直接对si排序,但可以对si的标号按si的大小进行排序,同时还要注意si有可能有相同大小的值。

        此外,取模运算的时候如果用位运算代替的话,会让效率高很多。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define MAXD 100010
    #define MAXK 5010
    const int D = (1 << 16) - 1;
    int N, K, a[MAXK], r[MAXK];
    char d[MAXD];
    int cmp(const void *_p, const void *_q)
    {
    int *p = (int *)_p;
    int *q = (int *)_q;
    return a[*p] - a[*q];
    }
    int get(int n)
    {
    int res = n;
    while(n)
    {
    res += n % 10;
    n /= 10;
    }
    return res;
    }
    void solve()
    {
    int i, j, k, num, t;
    for(i = 0; i < K; i ++)
    scanf("%d", &a[i]);
    a[K] = 0;
    for(i = 0; i < K; i ++)
    r[i] = i;
    qsort(r, K, sizeof(r[0]), cmp);
    r[K] = K;
    memset(d, '\0', sizeof(d));
    num = k = 0;
    for(i = 1; i <= N; i ++)
    {
    if(!d[i & D])
    {
    ++ num;
    while(num == a[r[k]])
    a[r[k ++]] = i;
    }
    t = get(i);
    if(t <= N)
    d[t & D] = '0';
    d[i & D] = '\0';
    }
    printf("%d\n", num);
    printf("%d", a[0]);
    for(i = 1; i < K; i ++)
    printf(" %d", a[i]);
    printf("\n");
    }
    int main()
    {
    while(scanf("%d%d", &N, &K) == 2)
    {
    solve();
    }
    return 0;
    }


  • 相关阅读:
    币值转换
    抓老鼠啊!亏了还是赚了
    打印沙漏
    秋季学习总结
    记忆中最深刻的三位老师
    自我介绍
    docker 安装redis 和 mysql
    centos 安装docker
    celery的简单使用
    django redis配置和简单使用
  • 原文地址:https://www.cnblogs.com/staginner/p/2300689.html
Copyright © 2011-2022 走看看