2007年分区联赛提高组之一 统计数字

本文解析了一道关于统计大量自然数出现频率的问题,通过哈希表实现高效统计,并提供了两种算法实现方案,一种使用哈希表进行统计后排序输出,另一种直接对输入数据排序后进行统计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2007年分区联赛提高组之一 统计数字

Time Limit:1000MS  Memory Limit:256000K
Total Submit:369 Accepted:151

Description

  某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。 

Input

  输入包含n+1行; 
  第一行是整数n,表示自然数的个数; 
  第2~n+1每行一个自然数。 

Output

  输出包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。 

Sample Input

8
2
4
2
4
5
100
2
100

Sample Output

2 3
4 2
5 1
100 2

Hint

40%的数据满足:1<=n<=1000 

80%的数据满足:1<=n<=50000 

100%的数据满足:1<=n<=200000,每个数均不超过1500 000 000(1.5*109) 

Source

elba


题意:

    统计出有几种数和出现的平率。题意很简单,明显就是要用,复杂高深的算法,经我细心挑选三天三夜,

选了哈希。用空间特别大的算法,特点是,查找快,统计容易。


var

  i,j,k,n,m,x,y,z,kk:longint;
  a:array[0..20001,0..2]of longint;
  b:array[0..20001]of longint;


function find(x:longint):longint;
var
  t:longint;
begin
  t:=t mod 20001;
  while (a[t,1]<>0) and (a[t,1]<>x) do
    t:=(t+1) mod 20001;
  find:=t;
end;


procedure f(x:longint);
var
  i:longint;
begin
  i:=find(x);
 if a[i,1]=0 then
   begin
     a[i,1]:=x;
     k:=k+1;
     b[k]:=x;
   end
   else
     a[i,2]:=a[i,2]+1;
end;


procedure kp(l,r:longint);
var
  i,j,key:longint;
begin
  if l>=r then exit;
  i:=l;
  j:=r;
  key:=b[(l+r) div 2];
  repeat
    while b[i]<key do inc(i);
    while b[j]>key do dec(j);
    if i<=j then
      begin
        b[0]:=b[i];
        b[i]:=b[j];
        b[j]:=b[0];
        inc(i);
        dec(j);


      end;


  until i>j;
  kp(l,j);
  kp(i,r);




end;


begin


  readln(n);
  for i:=1 to n do
    begin
      read(x);


      f(x);
    end;
  kp(1,k);
  for i:=1 to k do
  begin
    kk:=find(b[i]);
    writeln(a[kk,1],' ',a[kk,2]+1);
  end;


  end.

以上是高深算法;以下是卡gui点cu算法:

  • const
      maxn=200000;
    var   
      n,i:longint;
      t:int64;
      a:array[0..maxn]of longint;
    procedure kp(l,r:longint);
    var
      i,j:longint;
      key,temp:int64;
    begin
      if l>=r then exit;
      i:=l;j:=r;
      key:=a[l+random(r-l+1)];
      repeat
        while (a[i]<key) do inc(i);
        while (a[j]>key) do dec(j);
        if i<=j then
          begin
            temp:=a[i];a[i]:=a[j];a[j]:=temp;
            inc(i);dec(j);
          end;
      until i>j;
      kp(l,j);
      kp(i,r);
    end;
    
    begin
      readln(n);
      for i:=1 to n do readln(a[i]);
      kp(1,n);
      t:=1;
      for i:=1 to n do
        if a[i]<>a[i+1] then begin writeln(a[i],' ',t); t:=1; end
        else inc(t);
    end.
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值