PAT甲级题分类汇编——计算

计算类,指以数学运算为主或为背景的题。

题号 标题 分数 大意
1058 A+B in Hogwarts 20 特殊进制加法
1059 Prime Factors 25 分解素因数
1060 Are They Equal 25 一定精度下两数是否相等
1065 A+B and C (64bit) 20 大数加法与比较
1069 The Black Hole of Numbers 20 黑洞数
1073 Scientific Notation 20 科学计数法还原
1081 Rational Sum 20 有理数加法
1088 Rational Arithmetic 20 有理数运算
1096 Consecutive Factors 20 最长连续因数
1100 Mars Numbers 20 进制转换

这类题,普遍分数低,大多是20分。20分题放到乙级也没啥问题,比如1069、1081等。然而,即使是20分题,也可能要卡很久。

我挑了1059、1065、1088、1096共4道来做。

1059:

题目要求输出一个数的素因数分解。这么简单的题就不多讲了吧,直接上代码:

 1 #include <iostream>
 2 #include <map>
 3 #include <cmath>
 4
 5 bool isprime(int n)
 6 {
 7     int end = std::sqrt(n) + 1;
 8     for (int i = 2; i != end; ++i)
 9         if (n % i == 0)
10             return false;
11     return true;
12 }
13
14 int main(int argc, char const *argv[])
15 {
16     long n;
17     std::cin >> n;
18     std::cout << n << ‘=‘;
19     if (n == 1)
20     {
21         std::cout << ‘1‘;
22         return 0;
23     }
24     std::map<int, int> factors;
25     int prime = 2;
26     while (n > 1)
27     {
28         if (isprime(prime) && n % prime == 0)
29         {
30             ++factors[prime];
31             n /= prime;
32         }
33         else
34             ++prime;
35     }
36     int count = 0;
37     for (const auto& pair : factors)
38     {
39         if (count++)
40             std::cout << ‘*‘;
41         std::cout << pair.first;
42         if (pair.second > 1)
43             std::cout << ‘^‘ << pair.second;
44     }
45     return 0;
46 }

其实用 std::vector 也是可以的,但我懒。

需要注意的是 n==1 的检查,不过这个很容易发现。

1065:

要求判断两个64位整数相加是否大于另一个数。注意两个64位整数相加以后如果还保存在64位整数中是可能溢出的,并且test case里面一定会有这种情况。

所以要用更大的整数来做计算。然而C++标准库中并没有提供128位整数。这时,伟大的g++出现了,它提供了 __int128_t :

 1 #include <iostream>
 2
 3 int main(int argc, char const *argv[])
 4 {
 5     int t;
 6     std::cin >> t;
 7     std::cout << std::boolalpha;
 8
 9     for (int i = 1; i <= t; ++i)
10     {
11         __int128_t a, b, c;
12         int64_t ta, tb, tc;
13         std::cin >> ta >> tb >> tc;
14         a = ta; b = tb; c = tc;
15         std::cout << "Case #" << i << ": " << (a + b > c) << std::endl;
16     }
17
18     return 0;
19 }

于是这道题就被秒了。

C++标准库对整数类型的支持不太好,大整数的类只能自己写。至于是以二进制存储还是以十进制存储,那要看应用场景了。

1088:

在一个case上卡了好久,最后发现题目里有一句要用 long int ,WCNM。

难度没什么的,主要是对分子和分母有0或1的特殊情况的处理。

优雅的我写了一份很优雅的实现,又是template又是运算符重载的:

  1 #include <iostream>
  2 #include <exception>
  3
  4 template <typename T>
  5 class Rational
  6 {
  7 public:
  8     Rational() = default;
  9     Rational(T _num, T _den)
 10         : numerator(_num), denominator(_den)
 11     {
 12         reduce();
 13     }
 14     Rational(const Rational&) = default;
 15     Rational& operator=(const Rational&) = default;
 16
 17     Rational operator+(const Rational& _rhs) const noexcept
 18     {
 19         return Rational(numerator * _rhs.denominator + _rhs.numerator * denominator,
 20             denominator * _rhs.denominator);
 21     }
 22     Rational operator-(const Rational& _rhs) const noexcept
 23     {
 24         return Rational(numerator * _rhs.denominator - _rhs.numerator * denominator,
 25             denominator * _rhs.denominator);
 26     }
 27     Rational operator*(const Rational& _rhs) const noexcept
 28     {
 29         return Rational(numerator * _rhs.numerator,
 30             denominator * _rhs.denominator);
 31     }
 32     Rational operator/(const Rational& _rhs) const
 33     {
 34         if (_rhs.numerator == 0)
 35             throw std::exception();
 36         return Rational(numerator * _rhs.denominator,
 37             denominator * _rhs.numerator);
 38     }
 39
 40     template <typename U>
 41     friend std::istream& operator>>(std::istream&, Rational<U>&);
 42     template <typename U>
 43     friend std::ostream& operator<<(std::ostream&, const Rational<U>&);
 44 private:
 45     static T gcd(T _lhs, T _rhs)
 46     {
 47         if (_lhs < 0)
 48             _lhs = -_lhs;
 49         if (_lhs < _rhs)
 50             return gcd(_rhs, _lhs);
 51         if (_rhs == 0)
 52             return _lhs ? _lhs : 1;
 53         return gcd(_rhs, _lhs % _rhs);
 54     }
 55
 56     void reduce()
 57     {
 58         if (denominator < 0)
 59         {
 60             numerator = -numerator;
 61             denominator = -denominator;
 62         }
 63         auto factor = gcd(numerator, denominator);
 64         numerator /= factor;
 65         denominator /= factor;
 66     }
 67
 68     T numerator;
 69     T denominator;
 70 };
 71
 72 template <typename T>
 73 std::istream& operator>>(std::istream& _is, Rational<T>& _r)
 74 {
 75     T n, d;
 76     std::cin >> n;
 77     std::cin.get();
 78     std::cin >> d;
 79     _r = Rational<T>(n, d);
 80     return _is;
 81 }
 82
 83 template <typename T>
 84 std::ostream& operator<<(std::ostream& _os, const Rational<T>& _r)
 85 {
 86     auto r = _r;
 87     bool neg = false;
 88     if (r.numerator < 0)
 89     {
 90         neg = true;
 91         r.numerator = -r.numerator;
 92         _os << "(-";
 93     }
 94     if (r.denominator == 1)
 95         _os << r.numerator;
 96     else
 97     {
 98         if (r.numerator >= r.denominator)
 99         {
100             _os << (r.numerator / r.denominator) << ‘ ‘;
101             r.numerator %= r.denominator;
102         }
103         _os << r.numerator << ‘/‘ << r.denominator;
104     }
105     if (neg)
106         _os << ‘)‘;
107     return _os;
108 }
109
110 int main(int argc, char const *argv[])
111 {
112     Rational<long long> lhs, rhs;
113     std::cin >> lhs >> rhs;
114     std::cout << lhs << " + " << rhs << " = " << (lhs + rhs) << std::endl;
115     std::cout << lhs << " - " << rhs << " = " << (lhs - rhs) << std::endl;
116     std::cout << lhs << " * " << rhs << " = " << (lhs * rhs) << std::endl;
117     std::cout << lhs << " / " << rhs << " = ";
118     try
119     {
120         std::cout << (lhs / rhs) << std::endl;
121     }
122     catch(const std::exception& e)
123     {
124         std::cout << "Inf" << std::endl;
125     }
126     return 0;
127 }

优雅个屁,考试要来不及的。

顺便讲讲写自定义类(特指有成员方法的类而非简单的结构体)和模板的技巧。

构造函数最好给一个默认的,Rule of Three/Five规定的方法最好显式 =default 写出来。

参数尽量用引用,看情况要不要加 const ,大多都是要加的。相应地,成员方法能用 const 修饰的一定要加上去。

对于模板类的友元函数,模板类中还要再套模板,而且要用不一样的类型名称。

以上规则如果不遵守,很可能会编译错误,而且错误信息看起来比较累。

1096:

要求输出给定整数的的分解中可以出现的最长连续因数。乍一看有一点难,但稍微想一想就会发现,这串因数不会太长,因为阶乘是很大的。所以可以一个一个试这串因数中的最小数,连续很多个因数只有没几种情况需要试,到连续两个的情况,也是O(sqrt(n))时间复杂度能搞定的。至于单个因数则需要单独讨论一下,因为试到根号n就可以了,而如果不停止的话会超时。

 1 #include <iostream>
 2 #include <utility>
 3 #include <cmath>
 4
 5 int main(int argc, char const *argv[])
 6 {
 7     int n;
 8     std::cin >> n;
 9
10     try
11     {
12         for (int count = 11; count > 1; --count)
13         {
14             for (int min = 2; ; ++min)
15             {
16                 long product = 1;
17                 for (int factor = min; factor != min + count; ++factor)
18                     product *= factor;
19                 if (product > n)
20                     break;
21                 if (n % product == 0)
22                     throw std::pair<int, int>(count, min);
23             }
24         }
25         int end = std::sqrt(n) + 1;
26         for (int factor = 2; factor != end; ++factor)
27             if (n % factor == 0)
28                 throw std::pair<int, int>(1, factor);
29         throw std::pair<int, int>(1, n);
30     }
31     catch(const std::pair<int, int>& pair)
32     {
33         std::cout << pair.first << std::endl;
34         for (int i = pair.second; i != pair.second + pair.first - 1; ++i)
35             std::cout << i << ‘*‘;
36         std::cout << pair.second + pair.first - 1 << std::endl;
37     }
38
39     return 0;
40 }

长度的初始值是11,是因为2*3*...*13是大于2^31的,而2*3*...*12是小于2^31的,因此长度不会超过11。

总之,计算类题目没有难度,但是要避坑。坑依然是边界条件,包括最小的数(0、1、2等)与很大的数(int放不下的)。

原文地址:https://www.cnblogs.com/jerry-fuyi/p/11344229.html

时间: 2024-10-05 00:28:02

PAT甲级题分类汇编——计算的相关文章

PAT甲级题分类汇编——杂项

集合.散列.数学.算法,这几类的题目都比较少,放到一起讲. 题号 标题 分数 大意 类型 1063 Set Similarity 25 集合相似度 集合 1067 Sort with Swap(0, i) 25 通过与0号元素交换来排序 数学 1068 Find More Coins 30 子集和问题 算法 1070 Mooncake 25 背包问题 算法 1078 Hashing 25 散列 散列 1085 Perfect Sequence 25 符合约束的最大数列长度 集合 1092 To

PAT甲级题分类汇编——线性

线性类,指线性时间复杂度可以完成的题.在1051到1100中,有7道: 题号 标题 分数 大意 时间 1054 The Dominant Color 20 寻找出现最多的数 200ms 1061 Dating 20 寻找字符串中相同字符 200ms 1071 Speech Patterns 25 寻找出现最多的单词 300ms 1077 Kuchiguse 20 字符串共同后缀 150ms 1082 Read Number in Chinese 25 中文读数 400ms 1084 Broken

PAT甲级题分类汇编——理论

理论这一类,是让我觉得特别尴尬的题,纯粹是为了考数据结构而考数据结构.看那Author一栏清一色的某老师,就知道教数据结构的老师的思路就是和别人不一样. 题号 标题 分数 大意 Author 1051 Pop Sequence 25 判断一个序列是否是pop序列 CHEN, Yue 1052 Linked List Sorting 25 链表排序 CHEN, Yue 1057 Stack 30 一个有中位数功能的stack CHEN, Yue 1074 Reversing Linked List

PAT甲级题分类汇编——树

AVL树好难!(其实还好啦~) 我本来想着今天应该做不完树了,没想到电脑里有一份讲义,PPT和源代码都有,就一遍复习一遍抄码了一遍,更没想到的是编译一遍通过,再没想到的是运行也正常,最没想到的是一遍AC. 其实很多题都有数,std::set 之类用的是红黑树,据说很复杂,比AVL树还要复杂的那种.但是,用到这些设施的题,都不在这一分类下,这一分类下的题,因为题目要求自己建树,也就不用标准库设施了. 大多数题中,树在内存中都是连续存放的.不是像完全二叉树那样的连续,是物理上连续而逻辑上用数组下表代

PAT甲级题

A 1001 #include<cstdio> int main(){ int a,b,res[10]; long long sum; scanf("%d%d",&a,&b); sum=a+b; if(sum<0){ sum=-sum; printf("-"); } int i=0; if(sum==0) printf("0"); while(sum>0){ res[i++]=sum%10; sum=sum

PAT甲级考前整理

终于在考前,刷完PAT甲级130道题目,不容易!!!每天沉迷在刷题之中而不能超脱,也是一种境界.PAT甲级题目总的说卡题目的比较多,卡测试点的比较少,有些题目还会有题意混淆,这点就不吐槽了吧.静下心来耍这130道题,其实磨练的是一种态度与手感,养成的是一种习惯.热爱AC没有错!! 130道题目主要的考点: 1.排序:快速排序,直接插入排序,希尔排序,分治排序,堆排序. 2.图论:拓扑排序.最短路径.深度搜索.广度搜索. 3.树:树的遍历.完全二叉树.AVL. 4.其他:并查集,模拟,哈希.背包.

PAT甲级考试题库1001 A+B Format 代码实现及相关知识学习

准备参加九年九月份的PAT甲级证书考试,对网站上的题目进行总结分析: 1001题 A+B Format (20 分) Calculate a+b and output the sum in standard format -- that is, the digits must be separated into groups of three by commas (unless there are less than four digits). 计算a+b的值并以一定格式输出其和sum(数字需要

PAT甲级1005 Spell It Right

题目:PAT甲级 1005 题解:水题.看到题目的第一时间就在想一位一位的mod,最后一加一转换就完事了.结果看到了N最大为10的100的次方,吓得我赶紧放弃这个想法... 发现碰到这种情况用字符串十分好用,这道题应该考察的就是这一点.大致思路就是把数字的每一位放到字符串中,然后通过ASCII码得到每一位的相加结果num,然后把num一位一位的放到stack中,使用stack是因为它先进先出的特性,最后输出就行了. 代码: 1 #include<cstdio> 2 #include<qu

PAT 1012 数字分类 C语言

给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字: A1 = 能被5整除的数字中所有偶数的和: A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4...: A3 = 被5除后余2的数字的个数: A4 = 被5除后余3的数字的平均数,精确到小数点后1位: A5 = 被5除后余4的数字中最大数字. 输入格式: 每个输入包含1个测试用例.每个测试用例先给出一个不超过1000的正整数N,随后给出N个不超过1000的待分类的正整数.数字间以空格分隔. 输出格式: