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;
    }


  • 相关阅读:
    linux之awk命令
    HDU 2097 Sky数 进制转换
    HDU 2077 汉诺塔IV
    HDU 2094 产生冠军 dfs加map容器
    HDU 2073 叠框
    HDU 2083 简易版之最短距离
    HDU 2063 过山车 二分匹配
    天梯 1014 装箱问题
    天梯 1214 线段覆盖
    天梯 1098 均分纸牌
  • 原文地址:https://www.cnblogs.com/staginner/p/2300689.html
Copyright © 2011-2022 走看看