NOIP2007统计数字

题面:

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

样例输入:

8
2
4
2
4
5
100
2
100

样例输出:

2 3
4 2
5 1
100 2

数据范围:N <= 200000

这个题因为数据范围很小,所以是一道水题,直接用sort就可以水过。时间复杂度O(nlogn)。

代码:

#include <stdio.h>
#include <algorithm>
int data[200010];
#define gi(a) do {                             \
  register char ch;                           while((a = getchar()) > ‘9‘ || a < ‘0‘);           for(a -= ‘0‘; (ch = getchar()) >= ‘0‘ && ch <= ‘9‘; a = a*10+ch-‘0‘); } while(0)
int main() {
  register int i, cnt = 0, N;
  gi(N);
  for(i = 1; i <= N; i++)
    gi(data[i]);
  std::sort(data+1, data+1+N);
  for(i = 1; i <= N; i++) {
    cnt++;
    if(data[i] != data[i+1]) {
      printf("%d %d\n", data[i], cnt);
      cnt = 0;
    }
  }
}

实测144ms

但是如果数据卡sort(这个题数据良心不卡sort),或者N的范围更大,那么我们就要想想更好的算法了。

因为数字是固定不变的,我们首先可以想到一个很常规的算法:

开很多个桶,如果数字a出现了一次,那么桶a就++,最后把桶扫一遍。

但是如果数字太大,那么开很多个桶就会很浪费空间,甚至爆内存。

可以再开一个哈希表优化:

首先扫一遍,把值放进哈希表里,记录++。

然后把哈希表里面记录的数据扫一遍,排序输出。

设不重复的数字为m个,可见m <= n

时间复杂度O(mlogm+n*k),k取决于哈希函数的优劣(人品)

代码如下:

#include <stdio.h>
#include <algorithm>
#define MAXN 200010
#define gi(a) do {                             \
  register char ch;                           while((a = getchar()) > ‘9‘ || a < ‘0‘);           for(a -= ‘0‘; (ch = getchar()) >= ‘0‘ && ch <= ‘9‘; a = a*10+ch-‘0‘); } while(0)
struct number {
  int num, cnt;
};
number vis[MAXN];
number array[MAXN];
inline bool comp(const number &a, const number &b) {
  return a.num < b.num;
}
inline void hash(const int &a) {
  int key = a%MAXN;
  while(vis[key].cnt && vis[key].num != a) key++;
  if(vis[key].cnt == 0) vis[key].num = a;
  vis[key].cnt++;
}
int main() {
  int N, tot = 0, a, i, j;
  gi(N);
  for(i = 1; i <= N; i++) {
    gi(a);
    hash(a);
  }
  for(i = 0; i <= MAXN-1; i++)
    if(vis[i].cnt)
      array[++tot] = vis[i];
  std::sort(array+1, array+tot+1, comp);
  for(i = 1; i <= tot; i++)
    printf("%d %d\n", array[i].num, array[i].cnt);
  return 0;
}

实测64ms

(其实就这两个代码速度在所有代码中都是最快的,无论是不是加了优化)

时间: 2024-10-10 11:00:45

NOIP2007统计数字的相关文章

统计数字noip2007

7909:统计数字 总时间限制:  1000ms 内存限制:  65536kB 描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果. 输入 包含n+1行:第一行是整数n,表示自然数的个数:第2~n+1每行一个自然数. 40%的数据满足:1<=n<=1000:80%的数据满足:1<=n<=50000:100%的数据满足:1<=n

统计数字

原题链接:https://www.luogu.org/problem/show?pid=1097 纪念开学第一天,随手A掉一道大水题纪念一下. 题意非常明显,让我们排序并且统计数字,但数据量较大. 一开始想到最暴力的桶排序,但发现桶排序开不了那么大的数组,A不掉. 遂STL快排解决之.问题就在如何统计重复数字上. 受到夏令营day1t1启发,快排后统计数字,每次和前边的进行比较,如果相等则当前数字重复,开一个vis数组打上标记,开一个b数组外带一个附带指针t,用来记录重复数字重复出现了几次.如果

7909:统计数字

7909:统计数字 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果. 输入 包含n+1行:第一行是整数n,表示自然数的个数:第2~n+1每行一个自然数. 40%的数据满足:1<=n<=1000:80%的数据满足:1<=n<=50000:100%的

1164 统计数字

1164 统计数字 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题解 题目描述 Description [问题描述]某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109).已知不相同的数不超过10000 个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果. 输入描述 Input Description 第1行是整数n,表示自然数的个数.第2~n+1 行每行一个自

统计数字在排序数组中出现的次数

统计一个数字在排序数组中出现的次数: 可定义一个用于统计数字个数的变量count,然后从前往后遍历数组,看是否与所求数字相等,如果相等,则count++: 下面贴出代码: public class Solution {     public int GetNumberOfK(int [] array , int k) {         int count = 0;        for(int i=0;i<array.length;i++){            if(array[i]==k

腾讯面试题(统计数字出现的次数问题)

时间:2014.04.28 地点:基地二楼 日志:知道自己没有尝试着去试图改变,晓得错了~~ ---------------------------------------------------------------- 一.题目: 给你10分钟时间,根据上排给出十个数,在其下排填出对应的十个数 要求下排每个数都是先前上排那十个数在下排出现的次数. 上排的十个数如下: [0,1,2,3,4,5,6,7,8,9] 举一个例子, 数值:0,1,2,3,4,5,6,7,8,9 分配:6,2,1,0,

洛谷 P1097 统计数字(NOIp2007提高组T1)

题目描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果. 输入输出格式 输入格式: 输入文件count.in包含n+1行: 第一行是整数n,表示自然数的个数: 第2~n+1每行一个自然数. 输出格式: 输出文件count.out包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出.每行输出两个整数,分别是自然数和该数出现的次

NOIP2007 count 统计数字

问题描述 某次科研调查时得到了n个自然数,每个数均不超过1.5109.已知不相同的数不会超过10000个,现在需要统计这些自然数各自出现的个数,并按照自然数从小到大的顺序输出统计结果. 输入 输入文件count.in包含n+1行: 第一行是整数n,表示自然数的个数, 第2~n+1行每一行一个自然数. 输出 输出文件count.out包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出.每行输出两个整数,分别是自然数和该数出现的个数,其间用一个空格隔开. 输入输出样例 coun

[CareerCup] 18.4 Count Number of Two 统计数字2的个数

18.4 Write a method to count the number of 2s between 0 and n. 这道题给了我们一个整数n,让我们求[0,n]区间内所有2出现的个数,比如如果n=20,那么满足题意的是2, 12, 20,那么返回3即可.LeetCode上有一道很类似的题Factorial Trailing Zeroes,但是那道题求5的个数还包括了因子中的5,比如10里面也有5,这是两题的不同之处.那么首先这题可以用brute force来解,我们对区间内的每一个数字