本文为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分题,也可能要卡很久。

我挑了1059106510881096共4道来做。

1059:

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

  1. #include <iostream>
  2. #include <map>
  3. #include <cmath>
  4.  
  5. bool isprime(int n)
  6. {
  7. int end = std::sqrt(n) + ;
  8. for (int i = ; i != end; ++i)
  9. if (n % i == )
  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 == )
  20. {
  21. std::cout << '';
  22. return ;
  23. }
  24. std::map<int, int> factors;
  25. int prime = ;
  26. while (n > )
  27. {
  28. if (isprime(prime) && n % prime == )
  29. {
  30. ++factors[prime];
  31. n /= prime;
  32. }
  33. else
  34. ++prime;
  35. }
  36. int count = ;
  37. for (const auto& pair : factors)
  38. {
  39. if (count++)
  40. std::cout << '*';
  41. std::cout << pair.first;
  42. if (pair.second > )
  43. std::cout << '^' << pair.second;
  44. }
  45. return ;
  46. }

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

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

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 = ; 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 ;
  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 == )
  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 < )
  48. _lhs = -_lhs;
  49. if (_lhs < _rhs)
  50. return gcd(_rhs, _lhs);
  51. if (_rhs == )
  52. return _lhs ? _lhs : ;
  53. return gcd(_rhs, _lhs % _rhs);
  54. }
  55.  
  56. void reduce()
  57. {
  58. if (denominator < )
  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 < )
  89. {
  90. neg = true;
  91. r.numerator = -r.numerator;
  92. _os << "(-";
  93. }
  94. if (r.denominator == )
  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 ;
  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 = ; count > ; --count)
  13. {
  14. for (int min = ; ; ++min)
  15. {
  16. long product = ;
  17. for (int factor = min; factor != min + count; ++factor)
  18. product *= factor;
  19. if (product > n)
  20. break;
  21. if (n % product == )
  22. throw std::pair<int, int>(count, min);
  23. }
  24. }
  25. int end = std::sqrt(n) + ;
  26. for (int factor = ; factor != end; ++factor)
  27. if (n % factor == )
  28. throw std::pair<int, int>(, factor);
  29. throw std::pair<int, int>(, 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 - ; ++i)
  35. std::cout << i << '*';
  36. std::cout << pair.second + pair.first - << std::endl;
  37. }
  38.  
  39. return ;
  40. }

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

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

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

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

    本文为PAT甲级分类汇编系列文章. 集合.散列.数学.算法,这几类的题目都比较少,放到一起讲. 题号 标题 分数 大意 类型 1063 Set Similarity 25 集合相似度 集合 1067 ...

  2. PAT甲级题分类汇编——图

    本文为PAT甲级分类汇编系列文章. 图,就是层序遍历和Dijkstra这一套,#include<queue> 是必须的. 题号 标题 分数 大意 时间 1072 Gas Station 3 ...

  3. PAT甲级题分类汇编——树

    本文为PAT甲级分类汇编系列文章. AVL树好难!(其实还好啦~) 我本来想着今天应该做不完树了,没想到电脑里有一份讲义,PPT和源代码都有,就一遍复习一遍抄码了一遍,更没想到的是编译一遍通过,再没想 ...

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

    本文为PAT甲级分类汇编系列文章. 理论这一类,是让我觉得特别尴尬的题,纯粹是为了考数据结构而考数据结构.看那Author一栏清一色的某老师,就知道教数据结构的老师的思路就是和别人不一样. 题号 标题 ...

  5. PAT甲级题分类汇编——排序

    本文为PAT甲级分类汇编系列文章. 排序题,就是以排序算法为主的题.纯排序,用 std::sort 就能解决的那种,20分都算不上,只能放在乙级,甲级的排序题要么是排序的规则复杂,要么是排完序还要做点 ...

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

    本文为PAT甲级分类汇编系列文章. 线性类,指线性时间复杂度可以完成的题.在1051到1100中,有7道: 题号 标题 分数 大意 时间 1054 The Dominant Color 20 寻找出现 ...

  7. PAT甲级题分类汇编——序言

    今天开个坑,分类整理PAT甲级题目(https://pintia.cn/problem-sets/994805342720868352/problems/type/7)中1051~1100部分.语言是 ...

  8. 【转载】【PAT】PAT甲级题型分类整理

    最短路径 Emergency (25)-PAT甲级真题(Dijkstra算法) Public Bike Management (30)-PAT甲级真题(Dijkstra + DFS) Travel P ...

  9. PAT甲级题解分类byZlc

    专题一  字符串处理 A1001 Format(20) #include<cstdio> int main () { ]; int a,b,sum; scanf ("%d %d& ...

随机推荐

  1. [教程] Packt - Create a Game Environment with Blender and Unity by Darrin Lile

    学习了解如何使用Blender,photoshop和Unity创建自己的游戏环境!了解如何通过比以往更加集成的方式使用Blender和Unity,将自己的游戏设计变为现实.在Unity中创建测试版本 ...

  2. Grafana 在添加邮件和钉钉报警之后不报警的原因是没有重启grafana 不生效重启。

    即使在grafana页面上面添加也需要重启.配置邮件配置文件更需要重启. systemctl restart grafana-server.service

  3. mysql起容器的最精简命令

    亲测有效的 mysql 容器命令: #pull mysql:5.6 docker pull mysql:5.6 #起容器,映射3306端口,配置root用户密码 docker run -di --na ...

  4. flutter 不规则底部工具栏实现

    import 'package:flutter/material.dart'; import 'each_view.dart'; class BottomAppBarDemo extends Stat ...

  5. Ionic app IOS 在Xcode 模拟运行 真机调试

    1. 创建项目: sudo ionic start myApp tabs 2 cd 到刚才创建的项目 3. sudo ionic cordova platform add ios 把 ios 环境添加 ...

  6. 详解Django rest_framework实现RESTful API

    这篇文章主要介绍了详解Django rest_framework实现RESTful API,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 一.什么是REST 面向资源是R ...

  7. jenkins发布程序触发shell调用python脚本刷新akamai cdn api

    刷新cdn的流程:jenkins获取git中的代码,触发脚本推送到生产环境中(即cdn的源站) --> 触发脚本获取git工作目录的更新列表,将更新列表拼凑成带域名信息的url,写入到目录中 - ...

  8. 【转载】 谷歌集群数据分析 clusterdata-2011-2

    原文地址: https://www.twblogs.net/a/5c2dc304bd9eee35b21c418b/zh-cn ------------------------------------- ...

  9. ROS Software update

    http://packages.ros.org/ros/ubuntu

  10. Java中使用Socket连接判断Inputstream结束,java tcp socket服务端,python tcp socket客户端

    最近在试着用java写一个socket的服务器,用python写一个socket的客户端来完成二者之间的通信,但是发现存在一个问题,服务器方面就卡在读取inputsream的地方不动了,导致后面的代码 ...