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.
-