没有人我就来水一个
来源:第七届蓝桥杯省赛C++B组
算法标签:数论,最大公约数,辗转相减法
题目描述:
X星球的某个大奖赛设了 M 级奖励。
每个级别的奖金是一个正整数。
并且,相邻的两个级别间的比例是个固定值。
也就是说:所有级别的奖金数构成了一个等比数列。
比如:16,24,36,54,其等比值为:3/2。
现在,我们随机调查了一些获奖者的奖金数。
请你据此推算可能的最大的等比值。
输入格式
第一行为数字 N ,表示接下的一行包含 N 个正整数。
第二行 N 个正整数 Xi,用空格分开,每个整数表示调查到的某人的奖金数额。
输出格式
一个形如 A/B 的分数,要求 A、B 互质,表示可能的最大比例系数。
数据范围
0<N<100
0<Xi<1012
数据保证一定有解。
输入样例1:
3
1250 200 32
输出样例1:
25/4
输入样例2:
4
3125 32 32 200
输出样例2:
5/2
输入样例3:
3
549755813888 524288 2
输出样例3:
4/1
思路
我们要找一个数列的最大的等比值。
这种感觉和等差数列很相似,我们直接往GCD上靠
由于一串数据,排序之后肯定存在等差q
s= s1, s2 , s3 …sq … sn
s= aq^0,aq^1, aq^2 …a^q^k....aq^n
每个位次上都可以转换为[p/q]^w形式,即si=[s/a0,s/ai]^k
存在公比形如[p/q]^k
因为[p/q]^k>0,要使得整体最大则公比系数最大,则求K最大
k的限制条件
[p/q]^w是[p/q]^k的次幂
[p/q]^w=([p/q]^k)^s=[p/q]^k^s
则k是每一个w的约数
k最大就是wi的最大公约数
状如[p/q]^wi
我们现在转向了求每一个wi的最大公约数
[p/q]^k = [p^k/q^k]
我们可以直接求取分子分母
则分别求分子分母指数最大公约数
题目代码
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=110;
int n;
LL x[N],a[N],b[N];
LL gcd(LL a,LL b)//辗转相除
{
return b?gcd(b,a%b):a;
}
LL gcd_sub(LL a,LL b)//辗转相减
{
if(b>a)swap(a,b);
if(b==1)return a;
return gcd_sub(b,a/b);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)cin>>x[i];//读入
sort(x,x+n);
LL dd=0;
int cnt =0;
for(int i=1;i<n;i++)
{
if(x[i]!=x[i-1])//去重
{
dd =gcd(x[i],x[0]);//最大公约数
a[cnt] = x[i]/dd;
b[cnt] = x[0]/dd;
cnt++;
}
}
LL up = a[0],down = b[0];//up分子 down分母
for(int i=1;i<cnt;i++)//分开求分子分母的指数最大公约数
{
up = gcd_sub(up,a[i]);
down = gcd_sub(down,b[i]);
}
cout<<up<<"/"<<down;
return 0;
}
辗转相除和辗转相减有啥区别啊
效率不一样
为啥辗转相减没有减符号..
也许这就是所谓的老婆饼里没老婆,鱼香肉丝没有鱼吧
这个是辗转相减法的变式,用了原理而已,求出来的结果是幂的最大公约数。
因为两个数的幂次减,就是两个数相除
这个形容太太太形象了吧,赞一个