国王游戏【贪心】【数学】【高精度】

>Link

ybtoj国王游戏


>解题思路

很显然一道贪心(但是我一开始贪错了==)

我们设 a i 、 b i a_i、b_i aibi为第 i i i个人左右手上的数, s i s_i si为前 i i i个人所有人左手上数的乘积
考虑邻位交换,第 i i i个人与第 i + 1 i+1 i+1个人交换位置
则这两个位的最大值转换如下:
m a x ( s i − 1 b i , s i − 1 ∗ a i b i + 1 ) → m a x ( s i − 1 b i + 1 , s i − 1 ∗ a i + 1 b i ) max(\frac{s_{i-1}}{b_i},\frac{s_{i-1}*a_i}{b_{i+1}})→max(\frac{s_{i-1}}{b_{i+1}},\frac{s_{i-1}*a_{i+1}}{b_i}) max(bisi1,bi+1si1ai)max(bi+1si1,bisi1ai+1)

我们发现相邻两个位交换并不会影响到其他的位的值,并且
如果左边的值比右边的值大的话,就进行邻位交换,使最大值更小

所以比较左右两边式子

m a x ( s i − 1 b i , s i − 1 ∗ a i b i + 1 ) , m a x ( s i − 1 b i + 1 , s i − 1 ∗ a i + 1 b i ) max(\frac{s_{i-1}}{b_i},\frac{s_{i-1}*a_i}{b_{i+1}}),max(\frac{s_{i-1}}{b_{i+1}},\frac{s_{i-1}*a_{i+1}}{b_i}) max(bisi1,bi+1si1ai)max(bi+1si1,bisi1ai+1)
[两边除以 s i − 1 s_{i-1} si1]
m a x ( 1 b i , a i b i + 1 ) , m a x ( 1 b i + 1 , a i + 1 b i ) max(\frac{1}{b_i},\frac{a_i}{b_{i+1}}),max(\frac{1}{b_{i+1}},\frac{a_{i+1}}{b_i}) max(bi1,bi+1ai)max(bi+11,biai+1)
[两边再乘上 b i ∗ b i + 1 b_i*b_{i+1} bibi+1]
m a x ( b i + 1 , a i ∗ b i ) , m a x ( b i , a i + 1 ∗ b i + 1 ) max(b_{i+1},a_i*b_i),max(b_{i},a_{i+1}*b_{i+1}) max(bi+1,aibi)max(bi,ai+1bi+1)

因为 a i ∗ b i > b i , a i + 1 ∗ b i + 1 > b i + 1 a_i*b_i>b_i,a_{i+1}*b_{i+1}>b_{i+1} aibi>biai+1bi+1>bi+1
所以我们只用比较 a i ∗ b i a_i*b_i aibi a i + 1 ∗ b i + 1 a_{i+1}*b_{i+1} ai+1bi+1 就行了

得出,我们按照 a i ∗ b i a_i*b_i aibi从小到大把大臣们排序就行了
最后这道题需要用高精度==


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1010
#define maxn 4000
using namespace std;

struct node
{
    
    
	int a, b;
} s[N];
int n, A, B, ans[maxn + 5], w[maxn + 5], p[maxn + 5];

bool cmp (node aa, node bb) {
    
    return aa.a * aa.b < bb.a * bb.b;}
void gjcheng (int x)
{
    
    
	int g = 0;
	for (int i = maxn; i > 0; i--)
	{
    
    
		w[i] = w[i] * x + g;
		g = w[i] / 10;
		w[i] %= 10;
	}
}
void gjchu (int x)
{
    
    
	int g = 0, t = 0;
	while (w[t] == 0 && t < maxn) t++;
	for (int i = t; i <= maxn; i++)
	{
    
    
		p[i] = w[i] + g;
		g = p[i] % x * 10;
		p[i] /= x;
	}
}
void write ()
{
    
    
	int l = 0;
	while (ans[l] == 0 && l < maxn) l++;
	for (int i = l; i <= maxn; i++)
	  putchar (ans[i] + '0');
}

int main()
{
    
    
	scanf ("%d%d%d", &n, &A, &B);
	for (int i = 1; i <= n; i++) scanf ("%d%d", &s[i].a, &s[i].b);
	sort (s + 1, s + 1 + n, cmp);
	int g = 0;
	w[maxn] = A;
	for (int i = maxn; i > 0; i--)
	{
    
    
		w[i] += g;
		g = w[i] / 10;
		w[i] %= 10;
	}
	for (int i = 1; i <= n; i++)
	{
    
    
		memset (p, 0, sizeof (p));
		gjchu (s[i].b);
		for (int j = 0; j <= maxn; j++)
		{
    
    
			if (ans[j] > p[j]) break;
			if (ans[j] < p[j])
			{
    
    
				for (int k = 0; k <= maxn; k++) ans[k] = p[k];
				break;
			}
		}
		gjcheng (s[i].a);
	}
	write();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/112389448