问题 V: 有理数的个数
题目描述
任何一个有理数都可以表示成M/N的形式(M,N均为正整数)。例如1/2,2/4,3/6都是等值的有理数。给定若干有理数,等值有理数的值只能算一个,问这些有理数含有多少个值,并按从小到大输出各值及该值的有理数个数。
输入
第一行是整数n,表示随后有n组测试数据(n不超过10)。
每一组测试数据的第一行是一个整数m(m<=100000),随后有m行,每一行都是A/B的形式, 1<=A,B<=1000000000
输出
对于每一组测试数据,输出要求如下,第一行输出有理数值的个数p,随后的p行按从小到大的次序每一行输出一个A/B形式的值及其对应的有理数个数,用空格分开,要求A/B是最简分数。
样例输入
<span style="color:#333333"><span style="color:#333333">2
2
1/3
1/4
4
1/1
1/2
7/14
7/7
样例输出
<span style="color:#333333"><span style="color:#333333">2
1/4 1
1/3 1
2
1/2 2
1/1 2
之前没接触过STL,C语言AC代码如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct fraction
{
int a;///分子
int b;///分母
double c;///商
}frac[100000];
int cmp(const void *m,const void *n)///qsort排序函数
{
return (*(struct fraction*)m).c>(*(struct fraction*)n).c;
}
int GCD(int x,int y)///求最大公约数,化简分式
{
int t;
while(y!=0)
{
t=x%y;
x=y;
y=t;
}
return x;
}
int main()
{
int n,m,num;///num记录不同分式的个数
int y[100000],o;
int i,j;
int gcd;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&m);
memset(y,0,sizeof(y));
num=1;
o=0;
for(j=0;j<m;j++)
{
scanf("%d/%d",&frac[j].a,&frac[j].b);
if(GCD(frac[j].a,frac[j].b)!=1)
{
gcd=GCD(frac[j].a,frac[j].b);
frac[j].a/=gcd;
frac[j].b/=gcd;
}
frac[j].c=frac[j].a*1.0/frac[j].b;
}
qsort(frac,m,sizeof(frac[0]),cmp);
y[o]=1;
for(j=1;j<m;j++)
{
if((frac[j].a==frac[j-1].a)&&(frac[j].b==frac[j-1].b))
y[o]+=1;
else
{
num+=1;
o+=1;
y[o]+=1;
}
}
printf("%d\n",num);
printf("%d/%d %d\n",frac[0].a,frac[0].b,y[0]);
o=0;
for(j=1;j<m;j++)
{
if((frac[j].a!=frac[j-1].a)||(frac[j].b!=frac[j-1].b))///输出不同的分式
{
o+=1;
printf("%d/%d %d\n",frac[j].a,frac[j].b,y[o]);
}
}
}
return 0;
}
之后看到了用STL写的版本:(用map结构)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <functional>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
struct fraction
{
int a,b;
fraction(int arg1,int arg2):a(arg1),b(arg2){};
bool operator<(const fraction& t)const
{
return (long long)a * t.b< (long long)b *t.a;
}
};
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
///Container
///1.map #include<map>
///function:insert();erase();find();
///lower_bound();查找第一个不小于k的元素
///upper_bound();查找第一个大于k的元素
///equal_range();返回pair<lower,upper>
int i,cas;
scanf("%d",&cas);
while(cas--)
{
int a,b,m;
cin>>m;
char c;
map<fraction,int>mp;
for(i=0;i<m;i++)
{
cin>>a>>c>>b;
int g=gcd(a,b);
mp[fraction(a/g,b/g)]++;
printf("%d %d\n",a/g,b/g);
}
cout<<mp.size()<<endl;
for(map<fraction,int>::iterator it = mp.begin();
it != mp.end(); it++)
{
if(it->second)
printf("%d/%d %d\n",it->first.a,it->first.b,it->second);
}
}
return 0;
}
由此看来,STL是真的很方便,但是用不好很容易超时,所以适当的优化很重要,还是需要继续学习的。。。