• jdoj 1402 特殊的数 代码及分析


        这是jobdu的好题,网上的解说都是用位运算的,但是我现在对位运算还不太了解,所以我的代码是用对数组的压缩使用来实现对小数目个数的统计的,也因此对存储空间的利用是不够充分的。

    原理解释:一个int是4个字节组成的。在这题里面,如果开10^6的数组,4*10^6B≈4MB,这还没加上运行程序命令所需要的内存。由此可见,这样开数组是必定MLE的。但是我们可以发现,对于这题而言,每个数中我们所需要的状态只有0,1,2三种,于是我就想到数组在内存中的存储方式,并模仿它建立起一个大小只有50000的int数组。10^6 / (log(2^31) / log(3))<50000,由于数的范围是1~10^6,所以令数(a-1)/50000得到的值作为行位置,(a-1)%50000得到的值作为列位置,由此,一个100w的数组就被压缩成一个20行5w列的数组了。我的代码优化了输出,限定了输入的数的范围,最后遍历检测输出个数为1的数。

        这种方法并不高效,我最多只能把它优化到1104kb 1610ms的运行内存和运行时间。

        下面是我的代码,供大家参考:

    View Code
     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<math.h>
     5 #define MAX 50000   //决定数组大小
     6 #define POW 3    //每个数的状态数量
     7 
     8 
     9 unsigned int cnt[MAX];
    10 
    11 unsigned int ten(int pow)   //这里我要特别提醒的是,C里面的pow函数返回值强制变成int后,可能得到的不是我们所想要的那个数
    12 {
    13     unsigned int back;
    14 
    15     back=1;
    16     while(pow--)back*=POW;
    17 
    18     return back;
    19 }
    20 
    21 int amount(int a) //返回数a的个数
    22 {
    23     return (cnt[(a-1)%MAX]/ten((a-1)/MAX))%POW;
    24 }
    25 
    26 int main()
    27 {
    28     int i, c;
    29     int n, m;
    30     int min, max, maxn, minn;
    31 
    32     while(scanf("%d", &n)!=EOF)
    33     {
    34         memset(cnt, 0sizeof(cnt));
    35         max=maxn=c=0;min=minn=9999999;
    36         while(n--)
    37         {
    38             scanf("%d", &m);
    39             if(min>m)min=m;
    40             if(max<m)max=m;
    41             if(amount(m)!=2)cnt[(m-1)%MAX]+=ten((m-1)/MAX); //数的个数≥2就不用继续加了
    42         }
    43         for(i=min; i<=max; i++)
    44             if(amount(i)==1)
    45             {
    46                 if(!c)minn=i;
    47                 c++;
    48                 if(maxn<i)maxn=i;
    49             }
    50         if(c)printf("%d\n", c);
    51         else {printf("0\n");continue;}
    52         for(i=minn; c!=1; i++)
    53             if(amount(i)==1){printf("%d ", i);c--;}
    54         for(; i<=maxn; i++)
    55             if(amount(i)==1)printf("%d\n", i);
    56     }
    57 
    58     return 0;
    59 
    60 }

    written by Lyon

      

     

  • 相关阅读:
    AlwaysOn 执行备份任务
    SQL Server 2016 + AlwaysOn 无域集群
    IIS负载均衡
    利用mapWithState实现按照首字母统计的有状态的wordCount
    DStream转为DF的两种方式(突破map时元组22的限制)
    java.lang.reflect.InvocationTargetException at shade.com.datastax.spark.connector.google.common.base.Throwables.propagate(Throwables.java160)
    java学习路线
    Java线程间通信
    多线程对象及变量的并发访问
    Java多线程基础
  • 原文地址:https://www.cnblogs.com/LyonLys/p/jdoj_1402_Lyon.html
Copyright © 2020-2023  润新知