hnustOJ-1448-有理数个数

                                              问题 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是真的很方便,但是用不好很容易超时,所以适当的优化很重要,还是需要继续学习的。。。

猜你喜欢

转载自blog.csdn.net/qq_41759198/article/details/81133409