1448 分数有理化(qsort ,long long,辗转相除法的应用)

本文介绍了一个算法问题——如何统计并输出一系列有理数的唯一值及其出现次数。通过对输入的有理数进行排序和简化,确保了输出的是最简形式的有理数及其个数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1448: 有理数的个数
时间限制: 2 Sec  内存限制: 64 MB
提交: 421  解决: 65
[提交][状态][讨论版]
题目描述
任何一个有理数都可以表示成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

提示
来源
CYH


来源: http://acm.hnust.edu.cn/JudgeOnline/problem.php?id=1448
//思路 先用结构体存储数据
//排序规则 :1.double值小排在前面
                        2.相同的分子(分母)小放前面
//最后处理一下非最简分数(用欧几里德)

#include<stdio.h>
#include<stdlib.h>
int gcd(int a, int b)
{ return b == 0 ? a : gcd(b, a % b); }
typedef struct{
    long long a;
    long long b;
    double x;
}Con;
Con num[100001];
int cmp(const void *a,const void *b)
{
    if((*(Con *)a).x-(*(Con *)b).x)
        return (*(Con *)a).x>(*(Con *)b).x?1:-1;
    else
        return -(*(Con *)a).a+(*(Con *)b).a;
}
int main(void)
{
    int n,T;scanf("%d",&T);
    while(T--)
    {
        int count=1,T=1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%*c%lld",&num[i].a,&num[i].b);
            num[i].x=(double)num[i].a/(double)num[i].b;
        }
        qsort(num+1,n,sizeof(num[0]),cmp);
        for(int i=1;i<n;i++)
            if(num[i].x!=num[i+1].x) T++;
        printf("%d\n",T);
        for(int i=1;i<=n;i++)
        {
            if(num[i].x==num[i+1].x) count++;
            else 
            {
                int z=gcd(num[i].a,num[i].b);
                num[i].b/=z;num[i].a/=z;
                printf("%lld/%lld %d\n",num[i].a,num[i].b,count);
                count=1;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值