最大比例 公約數複用 【藍橋真題】 (c++)

最大比例

X星球的某個大獎賽設了M級獎勵。每個級別的獎金是一個正整數。
並且,相鄰的兩個級別間的比例是個固定值。
也就是說:所有級別的獎金數構成了一個等比數列。比如:
16,24,36,54
其等比值爲:3/2

現在,我們隨機調查了一些獲獎者的獎金數。
請你據此推算可能的最大的等比值。

輸入格式:
第一行爲數字N(1<N<100),表示接下的一行包含N個正整數
第二行N個正整數Xi(Xi<1 000 000 000 000),用空格分開。每個整數表示調查到的某人的獎金數額

要求輸出:
一個形如A/B的分數,要求A、B互質。表示可能的最大比例係數

測試數據保證了輸入格式正確,並且最大比例是存在的。

例如,
輸入:
3
1250 200 32

程序應該輸出:
25/4

再例如,輸入:
4
3125 32 32 200

程序應該輸出:
5/2

再例如,輸入:
3
549755813888 524288 2

程序應該輸出:
4/1

資源約定:
峯值內存消耗 < 256M
CPU消耗 < 3000ms

我的思路

  • 本題解析:所有獎金數構成一個等比數列,那麼隨機選取的某部分獎金數之間滿足(qq)k的關係,q爲公比,k爲平方數。
  • 思路說明:
  1. 選取的部分獎金先排序,然後將部分獎金數中所有相鄰兩個數A、B(A>B)兩兩分組,並計算對應的商 S = A/B = (qq)k
  2. 求得k,並將(qq)k代入計算,若不存在所有的S均能由((qq)k)n表示,則更新k(利用公約數的更新方式)
  3. 最後輸出 S ,即爲該算法的答案。
  • 公約數更新方式說明:求得的每對A/B = Si,i = 1 - (N-1),比如S1 = 625/16,S2 = 125/8,他們的最大比例這樣求,625/16 = (5/2)4,125/8 = (5/2)3,所以他們的最大比例等於4、3的最大公約數,即(5/2)1

算法展示

個人實現(答案有誤)

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;

LL N,in[101];//選取獎金總數 
LL mons[101],A,B,cnt;//mons:隨機選取的獎金數,A:除數,B:被除數,cnt:輔助變量。 
struct Gc{
	LL A,B;
	Gc(LL _A,LL _B):A(_A),B(_B)//約分 
	{
		LL _gcd = maxDiv(A,B);//求最大公約數 
		A/=_gcd;
		B/=_gcd; 
	} 
	LL maxDiv(LL A,LL B)//最大公約數求解 
	{
		if(B==0)return A;
		return maxDiv(B,A%B); 
	}
}; 
vector<Gc> gcs;
 
 
//求最大公約數 
LL comDiv(LL a,LL b)//q對應的不同比率之間的最大公約數 
{
	if(b==0) return a;
	return comDiv(b,a%b); 
} 

//求公比平方數
LL  powcnt(LL a)
{
	for(LL i =40;i>0;i--)//求得公約數 
	{
		if(pow(gcs[0].A,1.0/i)!=-1)return i;
	}
	return -1;
}
int main() {
	//輸入規模 
	cin>>N; 
	for(LL i = 0;i< N;i++)
	{
		cin>>in[i]; 
	}
	
	//升序排序 
	sort(in,in+N); 	
	if(N==2)
	{
		cout<<in[1]<<"/"<<in[0]<<endl;
		return 0; 
	}	 
	// 存入vector 
	for(LL i=0;i<N-1;i++)
	{
		if(in[i]!=in[i+1])gcs.push_back(Gc(in[i+1],in[i])); //添加每組數據 
	}
	
	 	
	//利用A,B最大公約數k求解 
	LL div = powcnt(gcs[0].A); 
	A = pow(gcs[0].A,1.0/div),B =pow(gcs[0].B,1.0/div);//記錄最小數 
	
	for(LL j= 0;j<gcs.size();j++)//比較公比平方數 
	{	
		LL cnt = powcnt(gcs[j].A);
		LL com = comDiv(div,cnt);
		if(div>com)div = com;
		if(div==1)break;
	} 
	
	cout<<pow(A,div)<<"/"<<pow(B,div)<<endl;
    return 0;
}

網上借鑑:https://blog.csdn.net/lbperfect123/article/details/87305381

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#define MAX 100005
typedef long long ll;
using namespace std;
 
ll a[105];
 
struct node
{
	ll x,y;
}p[105];
bool cmp(node xx,node yy)
{
	return xx.x<yy.x;
}
int main()
{
	int n;
	cin>>n;
	for(int t=0;t<n;t++)
	{
		scanf("%lld",&a[t]);
	}
	sort(a,a+n);
	ll s1;
	ll x,y;
	int cnt=0;
	for(int t=n-1;t>=1;t--)
	{
		if(a[t]!=a[t-1])
		{
		   s1=__gcd(a[t],a[t-1]);
		   p[cnt].x=a[t]/s1;
		   p[cnt++].y=a[t-1]/s1;  
	    }
	}
	sort(p,p+cnt,cmp);
	ll minn=p[0].x;
	x=p[0].x;
	y=p[0].y;
    for(int t=0;t<cnt-1;t++)
    {
    	if((p[t+1].x/p[t].x)<minn&&p[t+1].x/p[t].x!=1)
    	{
    		x=p[t+1].x/p[t].x;
    		y=p[t+1].y/p[t].y;
		}
	}
	
	printf("%lld/%lld",x,y);
	 
	return 0;
}

上文鏈接:交換瓶子 標記+歸位【藍橋真題】(c++)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章