http://codeup.cn/problem.php?cid=100000582&pid=1
题目
题目描述
先输入一组数,然后输入其分组,按照分组统计出现次数并输出,参见样例。
输入
输入第一行表示样例数m,对于每个样例,第一行为数的个数n,接下来两行分别有n个数,第一行有n个数,第二行的n个数分别对应上一行每个数的分组,n不超过100。
输出
输出m行,格式参见样例,按从小到大排。
样例输入
1
7
3 2 3 8 8 2 3
1 2 3 2 1 3 1
样例输出
1={2=0,3=2,8=1}
2={2=1,3=0,8=1}
3={2=1,3=1,8=0}
分析
1.变量
全局变量
【题目条件n<100那么n<maxn,若设数组则有0—101,用101做Link】
const int maxn=102;
int n,m;
对于每一组样例
未处理的数Num,去重排序过后的数NumUi
tmp暂存的分组号,去重排序过后的分组号Class
按照分组号在分组号的一位数组中插入数(未累积重复出现的次数)table[分组号][Link]
Link的解释:其中table[tmp][maxn - 1]++使得队尾元素【101】(n不超过100必不会达到101)在不断变大,作为下一个要插入的数组的下标以及当前数组中的数的个数
int Num[maxn]={},tmp,table[maxn][maxn]={};
set<int>NumUi;
set<int>Class;
2.输入
for(int i=0;i<n;i++){
//写入未处理的Num数,以便对应table;
//写入STL容器NumUI即为去重排序过后的数,表示{?=%d}
scanf("%d",&Num[i]);
NumUi.insert(Num[i]);
}
for(int i=0;i<n;i++){
//tmp为暂存的分组号
//写入STL容器Class即为去重排序过后的分组号
//按照分组号在分组号的一位数组中插入数(未累积重复出现的次数)
//table[tmp][maxn - 1]++使得队尾元素【101】(n不超过100必不会达到101)在不断变大,作为下一个要插入的数组的下标以及当前数组中的数的个数
scanf("%d",&tmp);
Class.insert(tmp);
table[tmp][table[tmp][maxn-1]++]=Num[i];
}
3.输出
3.0累积重复出现的次数
//tmp为暂存的数在该分组中的数量
tmp=0;
for(int i=0;i<100;i++){//注意上限不是maxn是100(n不超过100)
if(table[*cls][i]==*num)
tmp++;
}
printf("%d",tmp);
3.1
因为不知道如何找倒数第二个元素;
所以只能这么写,判定是否为第一个来写,
每一个的最后再}\n
or(set<int>::iterator cls=Class.begin();cls!=Class.end();cls++){
printf("%d={",*cls);
for(set<int>::iterator num=NumUi.begin();num!=NumUi.end();num++){
printf("%s%d=",num==NumUi.begin()?"":",",*num);
//tmp为暂存的数在该分组中的数量
tmp=0;
for(int i=0;i<100;i++){//注意上限不是maxn是100(n不超过100)
if(table[*cls][i]==*num)
tmp++;
}
printf("%d",tmp);
}
printf("}\n");
}
AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=102;
int n,m;
int main()
{
while(scanf("%d",&m)!=EOF)
{
while(m--)
{
scanf("%d",&n);
int Num[maxn]={},tmp,table[maxn][maxn]={};
set<int>NumUi;
set<int>Class;
for(int i=0;i<n;i++){
//写入未处理的Num数,以便对应table;
//写入STL容器NumUI即为去重排序过后的数,表示{?=%d}
scanf("%d",&Num[i]);
NumUi.insert(Num[i]);
}
for(int i=0;i<n;i++){
//tmp为暂存的分组号
//写入STL容器Class即为去重排序过后的分组号
//按照分组号在分组号的一位数组中插入数(未累积重复出现的次数)
//table[tmp][maxn - 1]++使得队尾元素【101】(n不超过100必不会达到101)在不断变大,作为下一个要插入的数组的下标以及当前数组中的数的个数
scanf("%d",&tmp);
Class.insert(tmp);
table[tmp][table[tmp][maxn-1]++]=Num[i];
}
for(set<int>::iterator cls=Class.begin();cls!=Class.end();cls++){
printf("%d={",*cls);
for(set<int>::iterator num=NumUi.begin();num!=NumUi.end();num++){
printf("%s%d=",num==NumUi.begin()?"":",",*num);
//tmp为暂存的数在该分组中的数量
tmp=0;
for(int i=0;i<100;i++){//注意上限不是maxn是100(n不超过100)
if(table[*cls][i]==*num)
tmp++;
}
printf("%d",tmp);
}
printf("}\n");
}
}
}
return 0;
}
写题过程中的错误
错误代码
以id[1000100]作为hash表;1000100为表长;H(key)=组号*100+数
数的大小没说在100以内,100010仍有可能会有数组越界或者重复
#include<bits/stdc++.h>
using namespace std;
int n,m,id[1000100]= {};
void hash(int x,int y,int num[])//组号*100+数
{
num[x*100+y]++;
return;
}
int main()
{
while(scanf("%d",&m)!=EOF)
{
while(m--)
{
scanf("%d",&n);
int x,y[n];
memset(id,0,sizeof(id));
set<int>fz;
set<int>zno;
for(int i=0; i<n; i++)
{
scanf("%d",&y[i]);
fz.insert(y[i]);
}
for(int i=0; i<n; i++)
{
scanf("%d",&x);
zno.insert(x);
hash(x,y[i],id);
}
for(set<int>::iterator it=zno.begin(); it!=zno.end(); it++)
{
printf("%d={",*it);
for(set<int>::iterator its=fz.begin(); its!=fz.end(); its++)
printf("%s%d=%d",its==fz.begin()?"":",",*its,id[*it*100+*its]);
printf("}\n");
}
}
}
return 0;
}