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 Buy or Not to Buy | 20 | 判断子集 | 集合 |
1093 | Count PAT's | 25 | 数子串 | 数学 |
1063就是 std::set 的使用,1092更水,这两道不做了。
集合-1085:
集合,表示方法多种多样,简单的有用数组表示的并查集,复杂的有基于红黑树的 std::set 。
但我也不知道当时整理的时候怎么把这道题分到集合里来了,但还真挺难说这道题怎么分类的。题目要求从输入数据中找出最大的子列(不一定连续)满足最大值不超过最小值的给定倍数。
实现方法比较简单,先排序,然后对于每个数,找到第一个超过它的倍数的数,迭代器相减一下就是长度。查找要用二分不能用线性,会超时。
#include <iostream>
#include <vector>
#include <algorithm> int main()
{
long num, para;
std::cin >> num >> para;
std::vector<long> data(num);
for (auto& i : data)
std::cin >> i;
std::sort(data.begin(), data.end());
int max = ;
for (int i = ; i != num; ++i)
{
if (i == || data[i] != data[i - ])
{
auto left = data.begin() + i;
auto right = data.end();
while (left < right)
{
auto mid = left + (right - left) / ;
if (*mid > data[i] * para)
right = mid;
else
left = mid + ;
}
int length = right - data.begin() - i;
if (length > max)
max = length;
if (right == data.end())
break;
}
}
std::cout << max;
}
散列-1078:
纯理论地考察散列知识,用单向平方探测法处理冲突。没什么好说的,就是很标准的散列。数据结构那个题集中有一道hard version,那个真的难。
#include <iostream>
#include <vector>
#include <cmath> bool is_prime(int _num)
{
if (_num == )
return false;
if (_num > && _num % == )
return false;
int end = std::sqrt(_num);
for (int i = ; i <= end; i += )
if (_num % i == )
return false;
return true;
} int main(int argc, char const *argv[])
{
int m;
std::cin >> m;
while (!is_prime(m))
++m;
std::vector<bool> hash(m);
int n;
std::cin >> n;
for (int i = ; i != n; ++i)
{
try
{
int t;
std::cin >> t;
for (int j = ; j != m; ++j)
{
int h = (t + j * j) % m;
if (hash[h] == )
{
hash[h] = ;
if (i > )
std::cout << ' ';
std::cout << h;
throw ;
}
}
if (i > )
std::cout << ' ';
std::cout << '-';
}
catch (...)
{
;
}
}
return ;
}
数学-1067:
乍一看,完全没有思路。正常排序哪有这么玩的?显然,这道题不考排序,需要一点数学知识把问题转化一下。
对于一个序列,如果值与位置的集合相等,那么一定可以形成若干个环。这道题中需要考虑的是:一元环,即就在应该在的位置上的元素,以及0处于什么样的环中。
自己编几个数据试一下就会发现,需要交换的次数为:
当0处于0号位置时,序列长度+多元环个数-一元环个数(包括0);
当0号位置不是0时,序列长度+多元环个数-一元环个数-2。
#include <iostream>
#include <utility> int main(int argc, char const *argv[])
{
int n;
std::cin >> n;
std::pair<int, bool> data[n];
int loop = ;
int single = ;
for (auto& i : data)
std::cin >> i.first;
for (int i = ; i != n; ++i)
{
if (data[i].second)
continue;
data[i].second = ;
if (data[i].first == i)
++single;
else
{
++loop;
int t = data[i].first;
while (!data[t].second)
data[t].second = , t = data[t].first;
}
}
if (data[].first == )
std::cout << n + loop - single;
else
std::cout << n + loop - single - ; return ;
}
数学-1093:
要求数“PAT”的个数。如果一个个数的话肯定超时,毕竟题目中都说了数量很大要取模。
正常的算法也不麻烦。先从左向右遍历,数‘P’的数量,在遇到'A'时记录下来;再从右向左遍历,数'T'的数量,也在遇到'A'时记录下来;最后遍历,对每个'A'计算刚才记录的数的乘积并累加。
#include <iostream>
#include <string>
#include <vector> int main()
{
std::string str;
std::cin >> str;
std::vector<int> count_p(str.size());
std::vector<int> count_t(str.size());
long count = ;
for (int i = ; i != str.size(); ++i)
if (str[i] == 'P')
++count;
else if (str[i] == 'A')
count_p[i] = count;
count = ;
for (int i = str.size() - ; i >= ; --i)
if (str[i] == 'T')
++count;
else if (str[i] == 'A')
count_t[i] = count;
count = ;
for (int i = ; i != str.size(); ++i)
if (str[i] == 'A')
count += count_p[i] * count_t[i];
count %= ;
std::cout << count;
}
算法-1070:
贪心算法,在数据结构的Dijkstra中提到过一句,没有系统讲过。但是,这道题的算法相当显然,对每种月饼的单价排序,从高到低选择即可。
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cmath> struct Mooncake
{
double weight;
double price;
}; int main()
{
int num;
double demand;
std::cin >> num >> demand;
std::vector<Mooncake> product(num);
for (auto& p : product)
std::cin >> p.weight;
for (auto& p : product)
std::cin >> p.price;
std::sort(product.begin(), product.end(), [](const Mooncake& lhs, const Mooncake& rhs) {
return lhs.price / lhs.weight > rhs.price / rhs.weight;
});
double total = ;
double profit = ;
for (const auto& p : product)
{
double weight = p.weight > demand - total ? demand - total : p.weight;
total += weight;
profit += weight / p.weight * p.price;
if (std::abs(total - demand) < 0.001)
break;
}
std::cout.setf(std::ios::fixed);
std::cout << std::setprecision() << profit;
}
算法-1068:
这道题压轴,因为我不会。
因为不会,所以瞎写。先写了个递归实现,对每种硬币的数量枚举,其中递归调用函数。遇到有符合要求的组合时,就抛出异常,将硬币组合作为异常参数。结果两个样例竟然都过了,然而提交的结果是4个accept、1个wrong、2个timeout。毕竟递归了,时间复杂度是指数量级的,不超时才怪呢。
想不出更好的算法,去查了答案。这道题是01背包问题,属于动态规划算法,我还没学到,难怪不会做。而且这道题是01背包问题的特殊版,子集和问题,重量和价值都是数的大小。类似的还有著名的两数和、三数和、四数和等。
核心算法是抄的,来自这篇博客。
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> int main()
{
int num, target;
std::cin >> num >> target;
std::vector<int> coin(num);
for (auto& i : coin)
std::cin >> i;
std::sort(coin.begin(), coin.end(), std::greater<int>());
std::vector<std::vector<bool>> select(num);
for (auto& v : select)
v.resize(target + );
std::vector<int> total(target + );
for (int i = ; i != num; ++i)
for (int j = target; j >= coin[i]; --j)
if (total[j] <= total[j - coin[i]] + coin[i])
{
select[i][j] = true;
total[j] = total[j - coin[i]] + coin[i];
}
if (total[target] != target)
{
std::cout << "No Solution";
return ;
}
int price = target;
int which = num - ;
std::vector<int> found;
while (price)
{
if (select[which][price])
{
found.push_back(coin[which]);
price -= coin[which];
}
--which;
}
int count = ;
for (int i : found)
{
if (count++)
std::cout << ' ';
std::cout << i;
}
}
最后还要说一句,Eva你已经是一个大孩子了,要学会自己解决问题,别总是让我写算法。关键问题是你还老给我出难题。
PAT甲级题分类汇编——杂项的更多相关文章
- PAT甲级题分类汇编——图
本文为PAT甲级分类汇编系列文章. 图,就是层序遍历和Dijkstra这一套,#include<queue> 是必须的. 题号 标题 分数 大意 时间 1072 Gas Station 3 ...
- PAT甲级题分类汇编——树
本文为PAT甲级分类汇编系列文章. AVL树好难!(其实还好啦~) 我本来想着今天应该做不完树了,没想到电脑里有一份讲义,PPT和源代码都有,就一遍复习一遍抄码了一遍,更没想到的是编译一遍通过,再没想 ...
- PAT甲级题分类汇编——理论
本文为PAT甲级分类汇编系列文章. 理论这一类,是让我觉得特别尴尬的题,纯粹是为了考数据结构而考数据结构.看那Author一栏清一色的某老师,就知道教数据结构的老师的思路就是和别人不一样. 题号 标题 ...
- PAT甲级题分类汇编——排序
本文为PAT甲级分类汇编系列文章. 排序题,就是以排序算法为主的题.纯排序,用 std::sort 就能解决的那种,20分都算不上,只能放在乙级,甲级的排序题要么是排序的规则复杂,要么是排完序还要做点 ...
- PAT甲级题分类汇编——计算
本文为PAT甲级分类汇编系列文章. 计算类,指以数学运算为主或为背景的题. 题号 标题 分数 大意 1058 A+B in Hogwarts 20 特殊进制加法 1059 Prime Factors ...
- PAT甲级题分类汇编——线性
本文为PAT甲级分类汇编系列文章. 线性类,指线性时间复杂度可以完成的题.在1051到1100中,有7道: 题号 标题 分数 大意 时间 1054 The Dominant Color 20 寻找出现 ...
- PAT甲级题分类汇编——序言
今天开个坑,分类整理PAT甲级题目(https://pintia.cn/problem-sets/994805342720868352/problems/type/7)中1051~1100部分.语言是 ...
- 【转载】【PAT】PAT甲级题型分类整理
最短路径 Emergency (25)-PAT甲级真题(Dijkstra算法) Public Bike Management (30)-PAT甲级真题(Dijkstra + DFS) Travel P ...
- PAT甲级题解分类byZlc
专题一 字符串处理 A1001 Format(20) #include<cstdio> int main () { ]; int a,b,sum; scanf ("%d %d& ...
随机推荐
- Centos7 中查找文件、目录、内容
1.查找文件 find / -name ‘filename’ 2.查找目录 find / -name ‘path’ -type d 3.查找内容 find . | xargs grep -ri ‘co ...
- 生成模型 VS 判别模型 (含义、区别、对应经典算法)
从概率分布的角度考虑,对于一堆样本数据,每个均有特征Xi对应分类标记yi. 生成模型:学习得到联合概率分布P(x,y),即特征x和标记y共同出现的概率,然后求条件概率分布.能够学习到数据生成的机制 ...
- PHP异步非阻塞fsockopen(本地可以非阻塞请求,服务器就一直执行异步的不成功) (未解决)
index.php /** * php异步请求 * * @param $host string 主机地址 * @param $path string 路径 * @param $param array ...
- php 将office文件(word/excel/ppt)转化为pdf(windows和linux只要安装对应组件应该就行)
一.配置环境 (1)配置php.ini 添加:extension=php_com_dotnet.dll com.allow_dcom = true // 去掉号,改为true 重启环境 (2) 安装 ...
- 从内核3.7版本开始,Linux就开始支持VXLAN 到了内核3.12版本,Linux对VXLAN的支持已经完备,支持单播和组播,IPv4和IPv6。
一.关于VXLAN VXLAN 是 Virtual eXtensible LANs 的缩写,它是对 VLAN 的一个扩展,是非常新的一个 tunnel 技术,在Open vSwitch中应用也非常多. ...
- 写了一个具有future接口的rust测试代码
写了一个具有future接口的rust测试代码 但没有实现future功能,内部是直接求值 struct Future<T> { t: T, } impl<T> Future& ...
- MacOS 安装配置 Laravel
简单介绍: Laravel是一个用PHP编写的免费开源Web框架.它是由Taylor Otwell创作的,遵循MVC开发方法. 截至2015年3月,Laravel被认为是最流行的基于PHP的框架之一. ...
- Flutter之BLOC
flutter_bloc 是一个bloc第三方库,这个库很方便的让你集成bloc模式,这个库结合了RXDart,先了解一下bloc 的模式吧 1,widget 触发event 事件 2,bloc 接收 ...
- typescript命名空间
/* 命名空间: 在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数.类.接口等放置到命名空间内 同Java的包..Net的命名空间一样,TypeScript的命名空间可以将代码包裹 ...
- Qt比较字符串Qstring是否相等
Qt比较字符串Qstring是否相等 QString str = "相等"; if(str ==QString::fromLocal8Bit("球形")) { ...