本文涉及知识点
[蓝桥杯 2016 省 AB] 最大比例
题目描述
X 星球的某个大奖赛设了 M M M 级奖励。每个级别的奖金是一个正整数。
并且,相邻的两个级别间的比例是个固定值。
也就是说:所有级别的奖金数构成了一个等比数列。比如:
16 , 24 , 36 , 54 16,24,36,54 16,24,36,54
其等比值为: 3 / 2 3/2 3/2。
现在,我们随机调查了一些获奖者的奖金数。
请你据此推算可能的最大的等比值。
输入格式
第一行为数字 N ( 0 < N < 100 ) N(0<N<100) N(0<N<100),表示接下的一行包含 N N N 个正整数。
第二行 N N N 个正整数 X i ( X i < 1 0 12 ) X_i(X_i<10^{12}) Xi(Xi<1012),用空格分开。每个整数表示调查到的某人的奖金数额。
输出格式
一个形如 A / B A/B A/B 的分数,要求 A A A、 B B B 互质。表示可能的最大比例系数。
测试数据保证了输入格式正确,并且最大比例是存在的。
样例 #1
样例输入 #1
3
1250 200 32
样例输出 #1
25/4
样例 #2
样例输入 #2
4
3125 32 32 200
样例输出 #2
5/2
样例 #3
样例输入 #3
3
549755813888 524288 2
样例输出 #3
4/1
提示
时限 3 秒, 256M。蓝桥杯 2016 年第七届省赛
蓝桥杯 2016 年省赛 A 组 J 题(B 组 J 题)。
证明过程
完整的等比数列,分解质因素后,各质因数的数量成等差数列,令其差为y。本题是残缺的等比数列,故质因素的数量是残缺的等差的数量。相邻两项的差分别为:k1y,k2y ⋯ \cdots ⋯,下文简称k1、k2 ⋯ \cdots ⋯ 任意元素或所有元素为k。对于任意质因数,k是未知的,但ky是已知的,就是下文的b[i]。如果k互质,则y就是gcd(ky)。如果k不互质,除以gcd(k)后,y更大。本题一定有解,故各质因数的k相同,即各质因数的y为gcd(ky)。如果ky为负数,结果是-gcd(ky)。由于倍率大于等于1,故正数(分子)取最大值,比负数(分母)取最大值更优。
解法
X升序排序。
获取x所有元素的质因数,出重。其实只要枚举任意两个不同的元素。
枚举各质因数z:
依次将x的包括z的次方放到数a中。b[i] = a[i+1]减a[i]。g = gcd(b)。
如果b全部为正,则分子包括:zg;否则分母包括zg。由于等差数量的差,要么全部为正,要么全部为负。
代码
核心代码
#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include <bitset>
using namespace std;
template<class T = int>
vector<T> Read(int n,const char* pFormat = "%d") {
vector<T> ret;
T d ;
while (n--) {
scanf(pFormat, &d);
ret.emplace_back(d);
}
return ret;
}
template<class T = int>
vector<T> Read( const char* pFormat = "%d") {
int n;
scanf("%d", &n);
vector<T> ret;
T d;
while (n--) {
scanf(pFormat, &d);
ret.emplace_back(d);
}
return ret;
}
string ReadChar(int n) {
string str;
char ch;
while (n--) {
do
{
scanf("%c", &ch);
} while (('\n' == ch));
str += ch;
}
return str;
}
template<class T = int>
class CUniqueFactorization
{
public:
CUniqueFactorization(T iPrime, int cnt) {
m_data.emplace_back(iPrime, cnt);
}
CUniqueFactorization(vector<T> primes = {}, vector<int> cnts = {}) {
for (int i = 0; i < primes.size(); i++) {
m_data.emplace_back(primes[i], cnts[i]);
}
}
CUniqueFactorization operator+ (const CUniqueFactorization& o)const {
CUniqueFactorization ret;
int i = 0, j = 0;
while ((i < m_data.size()) && (j < o.m_data.size())) {
if (m_data[i].first == o.m_data[j].first) {
int cnt = m_data[i].second + o.m_data[j].second;
if (0 != cnt)
{
ret.m_data.emplace_back(m_data[i].first, cnt);
}
i++, j++;
}
else if (m_data[i].first < o.m_data[j].first) {
ret.m_data.emplace_back(m_data[i]);
i++;
}
else {
ret.m_data.emplace_back(o.m_data[j]);
j++;
}
}
ret.m_data.insert(ret.m_data.end(), m_data.begin() + i, m_data.end());
ret.m_data.insert(ret.m_data.end(), o.m_data.begin() + j, o.m_data.end());
return ret;
}
CUniqueFactorization negation()const {
CUniqueFactorization ret;
ret = *this;
for (auto& [i, cnt] : ret.m_data) {
cnt *= -1;
}
return ret;
}
CUniqueFactorization One() const {
CUniqueFactorization ret;
ret = *this;
for (auto& [i, cnt] : ret.m_data) {
cnt *= 1;
}
return ret;
}
CUniqueFactorization GetValue(const CUniqueFactorization& o)const {
CUniqueFactorization ret;
for (const auto& [pri, cnt] : m_data) {
ret.m_data.emplace_back(pri, 0);
}
return ret + o;
};
pair<T, T> Union()const {
long long ll1 = 1, ll2 = 1;
for (auto [pri, cnt] : m_data) {
auto& ll = (cnt >= 0) ? ll1 : ll2;
for (int j = 0; j < abs(cnt); j++) {
ll *= pri;
}//可以用快速指数幂加速
}
return { ll1,ll2 };
}
vector<pair<T, int>> m_data;
};
template<class T = int>
class CUniqueFactorizationFactory {
public:
CUniqueFactorizationFactory(T iMax) {
T iMaxSqrt = sqrt(iMax) + 2;
m_vPrime = CreatePrime(iMaxSqrt);
}
CUniqueFactorization<T> Factorization(T x) {
CUniqueFactorization<T> ret;
for (const auto& iPre : m_vPrime) {
int cnt = 0;
while (0 == x % iPre) {
cnt++;
x /= iPre;
}
if (cnt > 0) {
ret.m_data.emplace_back(iPre, cnt);
}
}
if (x > 1) {
ret.m_data.emplace_back(x, 1);
}
return ret;
}
static vector<int> CreatePrime(int iMax)
{
vector<bool> isPrime(iMax + 1, true);
vector<int> vPrime;
for (int i = 2; i <= iMax; i++)
{
if (isPrime[i])
{
vPrime.emplace_back(i);
}
for (const auto& n : vPrime)
{
if (n * i > iMax) { break; }
isPrime[n * i] = false;
if (0 == i % n) { break; }
}
}
return vPrime;
}
vector<int> m_vPrime;
};
class Solution {
public:
pair<long long, long long> Ans(vector<long long>& a) {
const int N = a.size();
sort(a.begin(), a.end());
unordered_map<long long, vector<int>> ma;
CUniqueFactorizationFactory<long long> uff(a.back());
CUniqueFactorization<long long> uf3;
for (const auto& ii : a)
{
uf3 = uf3 + uff.Factorization(ii).One();
}
for (const auto& ii : a) {
auto uf = uff.Factorization(ii);
auto uf4 = uf3.GetValue(uf);
for (const auto& [pri, cnt] : uf4.m_data) {
ma[pri].emplace_back(cnt);
}
}
CUniqueFactorization<long long> ret;
for (const auto& [pri, v] : ma) {
long long g = 0;
int sign = 1;
for (int i = 1; i < v.size(); i++) {
g = gcd(g, v[i] - v[i - 1]);
if (v[i] - v[i - 1] < 0) { sign = -1; }
}
ret = ret + CUniqueFactorization<long long>(pri, sign * g);
}
return ret.Union();
}
};
int main() {
#ifdef _DEBUG
freopen("a.in", "r", stdin);
#endif // DEBUG
int n;
scanf("%d", &n);
auto a = Read<long long>(n,"%lld");
#ifdef _DEBUG
//Out(a, "a=");
#endif
auto [ll1,ll2] = Solution().Ans(a);
cout << ll1 << "/" << ll2 << std::endl;
return 0;
}
单元测试
vector<long long> a;
TEST_METHOD(TestMethod1)
{
a = { 1,1,1 };
auto [ll1, ll2] = Solution().Ans(a);
AssertEx(1LL, ll1);
AssertEx(1LL, ll2);
}
TEST_METHOD(TestMethod2)
{
a = { 2,10000000019LL };
auto [ll1, ll2] = Solution().Ans(a);
AssertEx(a[1], ll1);
AssertEx(a[0], ll2);
}
TEST_METHOD(TestMethod3)
{
a = { 10000000019LL ,2};
auto [ll1, ll2] = Solution().Ans(a);
AssertEx((long long)a[1], ll1);
AssertEx(a[0], ll2);
}
TEST_METHOD(TestMethod4)
{
a = { 1250 ,200, 32 };
auto [ll1, ll2] = Solution().Ans(a);
AssertEx((long long)25, ll1);
AssertEx(4LL, ll2);
}
TEST_METHOD(TestMethod5)
{
a = { 3125, 32, 32 ,200 };
auto [ll1, ll2] = Solution().Ans(a);
AssertEx((long long)5, ll1);
AssertEx(2LL, ll2);
}
TEST_METHOD(TestMethod6)
{
a = { 549755813888LL, 524288, 2 };
auto [ll1, ll2] = Solution().Ans(a);
AssertEx((long long)4, ll1);
AssertEx(1LL, ll2);
}
扩展阅读
我想对大家说的话 |
---|
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
失败+反思=成功 成功+反思=成功 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。