AcWing 1223. 最大比例

AcWing 1223. 最大比例

题目

X星球的某个大奖赛设了 M 级奖励。

每个级别的奖金是一个正整数。

并且,相邻的两个级别间的比例是个固定值。

也就是说:所有级别的奖金数构成了一个等比数列。

比如:16,24,36,54,其等比值为:3/2。

现在,我们随机调查了一些获奖者的奖金数。

请你据此推算可能的最大的等比值。

输入格式
第一行为数字 N ,表示接下的一行包含 N 个正整数。

第二行 N 个正整数 Xi,用空格分开,每个整数表示调查到的某人的奖金数额。

输出格式
一个形如 A/B 的分数,要求 A、B 互质,表示可能的最大比例系数。

数据范围
0 < N < 100 0<N<100 0<N<100
0 < X i < 1 0 12 0<X_i<10^{12} 0<Xi<1012
数据保证一定有解。

思路

对于 a 1... n a_{1...n} a1...n排序去重得到 b 1.. m b_{1..m} b1..m。将它们两两之间的比值求出,得到 r 2.. m r_{2..m} r2..m
r i = ( p q ) x i r_i = (\frac{p}{q})^{x_i} ri=(qp)xi
若我们已知p,q,x,那么,要求的最大值必然是 ( p q ) k (\frac{p}{q})^k (qp)k,其中 k = g c d ( x 2... m ) k=gcd(x_{2...m}) k=gcd(x2...m)。而如今我们并不知道它们分别为多少,仅知道它们的幂。
不妨设F(a,b)就是a,b之间的最佳比例,我们对于p,q分别计算,这里仅讨论p。
F ( a , b ) = F ( p x , p y )      ( y > x ) = p g c d ( x , y ) = p g c d ( x , y − x )     ( 这 里 采 用 辗 转 相 减 , 由 于 在 指 数 部 分 , 使 用 除 法 要 开 方 , 并 不 适 用 于 我 们 的 整 数 计 算 ) = F ( p x , p y − x ) \begin{aligned} F(a,b) &=F(p^x,p^y)~~~~(y>x)\\ &=p^{gcd(x,y)}\\ &=p^{gcd(x,y-x)}~~~(这里采用辗转相减,由于在指数部分,使用除法要开方,并不适用于我们的整数计算)\\ &=F(p^x,p^{y-x}) \end{aligned} F(a,b)=F(px,py)    (y>x)=pgcd(x,y)=pgcd(x,yx)   (使)=F(px,pyx)
从而可以得到最佳比例。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 105;
#define int long long
int a[N],n;
int up[N],down[N];

int gcd(int a,int b)
{
    return b == 0 ? a : gcd(b,a%b);
}

int pgcd(int a,int b)
{
    if(a > b)
        swap(a,b);
    if(a == b)
        return a;
    return pgcd(a,b/a);
}

signed main()
{
    cin>>n;
    for (int i = 1; i <= n; i ++ )
        cin>>a[i];
    sort(a+1,a+n+1);
    int m = unique(a+1,a+n+1) - a - 1;
    for (int i = 2; i <= m ; i ++)
    {
        int d = gcd(a[i],a[1]);
        up[i] = a[i] / d;
        down[i] = a[1] / d;
    }
    int u = up[2] , dw = down[2];
    for (int i = 2 ; i <= m ; i ++)
    {
        u = pgcd(u,up[i]);
        dw = pgcd(dw,down[i]);
    }
    cout<<u<<"/"<<dw;
    return 0;
}
堆排序是一种高效的排序算法,它利用了堆的数据结构来实现排序。堆是一个完全二叉树,具有以下性质:对于任意节点 i,其父节点的值小于等于子节点的值。 堆排序的基本思路如下: 1. 构建最大堆:将待排序的数组看作是一个完全二叉树,从最后一个非叶子节点开始,依次向上调整每个节点,使得以该节点为根的子树满足最大堆的性质。 2. 将堆顶元素与最后一个元素交换:将最大堆的堆顶元素(即数组的第一个元素)与数组最后一个元素交换位置,此时最大元素就位于数组的最后。 3. 调整堆:将剩余元素重新调整为最大堆。 4. 重复步骤 2 和步骤 3,直到所有元素都排序完成。 以下是堆排序的 C++ 代码实现: ```cpp #include <iostream> using namespace std; // 调整以 root 为根的子树为最大堆 void heapify(int arr[], int n, int root) { int largest = root; // 假设根节点最大 int left = 2 * root + 1; // 左子节点索引 int right = 2 * root + 2; // 右子节点索引 // 若左子节点大于根节点,更新最大值索引 if (left < n && arr[left] > arr[largest]) { largest = left; } // 若右子节点大于最大值节点,更新最大值索引 if (right < n && arr[right] > arr[largest]) { largest = right; } // 若最大值不是根节点,交换根节点和最大值 if (largest != root) { swap(arr[root], arr[largest]); // 递归调整交换后的子树 heapify(arr, n, largest); } } void heapSort(int arr[], int n) { // 构建最大堆 for (int i = n / 2 - 1; i >= 0; i--) { heapify(arr, n, i); } // 逐步取出最大值,调整堆 for (int i = n - 1; i > 0; i--) { swap(arr[0], arr[i]); heapify(arr, i, 0); } } int main() { int arr[] = {4, 10, 3, 5, 1}; int n = sizeof(arr) / sizeof(arr[0]); heapSort(arr, n); cout << "Sorted array: "; for (int i = 0; i < n; i++) { cout << arr[i] << " "; } cout << endl; return 0; } ``` 以上就是堆排序的基本思路和实现方法。堆排序的时间复杂度为 O(nlogn),其中 n 为数组的长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值