有理数的个数 STL-map实例应用

题目描述
任何一个有理数都可以表示成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是最简分数。
样例输入
2
2
1/3
1/4
4
1/1
1/2
7/14
7/7
样例输出
2
1/4 1
1/3 1
2
1/2 2
1/1 2
思路
有理数的个数首先要讨论的是有多少种有理数,其次要讨论每个有理数有多少个。
我想到的办法是建立一个自定义结构fraction{int a,b;double c;},a存分子,b存分母,c存a/b的结果。然后依次存入输入数据,把a/b约分为最小,用最大公约数去约分,然后按c排序,最后计数c相同的数量,输出每个有理数。
这样的做法时间复杂度很高。再学了STL后,知道了另一种方法–STL中有一种map的容器,是一种关联数组,一对多,这里声明方式map<类型a,类型b>,类型a在这里表示有理数a/b,类型b为该有理数的个数,类型a只能有一个,类型b可多个。在map里可以自动排序(可自定义排序方法),然后调用寄存器,输出map容器的所有值。

方法一(普通方法)

#include "cstdio"
#include "cstring"
#include "algorithm"
#include "iostream"
#include "cmath"
using namespace std;
const int MAX=1e5+5;
struct fraction
{
    int a,b;
    double c;
}stu[MAX];
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
bool cmp(fraction a,fraction b)
{
    return a.cint main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;iscanf("%d/%d",&stu[i].a,&stu[i].b);
             int g=gcd(stu[i].a,stu[i].b);
             stu[i].a=stu[i].a/g;
             stu[i].b=stu[i].b/g;
             stu[i].c=double(stu[i].a)/double(stu[i].b);
        }
        sort(stu,stu+n,cmp);
        /*for(int i=0;i
        int p=1;
        int i;
        //输出个数
        for(i=0;i1;i++)
        {
            if(stu[i].a!=stu[i+1].a || stu[i].b!=stu[i+1].b)
            {
                p++;
            }
        }
        printf("%d\n",p);
        p=1;
        for(i=0;iif(stu[i].a!=stu[i+1].a || stu[i].b!=stu[i+1].b)
            {
                printf("%d/%d %d\n",stu[i].a,stu[i].b,p);
                p=1;
            }else{
                p++;
            }
        }
        //printf("%d/%d %d\n",stu[i].a,stu[i].b,p);
    }
    return 0;
}

方法二(map)

#include 
#include 
using namespace std;

typedef long long LL;
struct fraction {
  int a, b; //a/b
  fraction(int arg1, int arg2): a(arg1), b(arg2) {}
  bool operator<(const fraction& t)const
  {
    return (LL)a * t.b < (LL)b * t.a;
  }
};

int gcd(int a, int b)
{
  return b == 0 ? a : gcd(b, a % b);
}

int main(  )
{
  int i, cas;

  scanf("%d", &cas);
  while(cas--) {
    int a, b, m;
    scanf("%d", &m);
    mapint> mp;
    for(i = 0; i < m; i++) {
      scanf("%d/%d", &a, &b);
      int g = gcd(a, b);
      mp[fraction(a / g, b / g)]++;
    }
    printf("%d\n", mp.size());
    for(mapint>::iterator iter = mp.begin();
        iter != mp.end(); iter++)
      printf("%d/%d %d\n", iter->first.a, iter->first.b, iter->second);
  }
  return 0;
}

练习网址
http://acm.hnust.cn/JudgeOnline/problem.php?id=1448

你可能感兴趣的:(C/C++,STL)