传送门
又是一道木有看题解就想出来的题
题意:
简而言之
一堆数
求排列
使这些数
经过操作后
最大值最小
解法:
注意:根据题意每个数都有两个数a,b,这里为了方便记作一个数
我们贪心的只考虑第n个数
由于是乘积
所以第n个数确定时
前n-1个数a的乘积就是确定的
所以可以先求出前n个数a的乘积mul
则我们现在需要确定第n个数的值
第n个数的值 即为前n个数a的乘积mul除以第n个数的a,b(都要除)
所以第n个数我们选择a( imes)b最大的数
前n-1个数a的乘积就变成mul(div)a
在按照上面方法继续求n-1的数,n-2的数……
求出所有数的值的最大值即为答案
我们不妨证明一下这样做的正确性:
若只有2个大臣
国王、大臣 左、右手分别为(a_0 b_0,a_1 b_1,a_2 b_2)
设(a_1 imes b_1<a_2 imes b_2)
那么
若把(a_1,b_1)放第2个位置 答案即为max((frac{a_0}{b_2},frac{a_0a_2}{b_1}))
若把(a_2,b_2)放第2个位置 答案即为max((frac{a_0}{b_1},frac{a_0a_1}{b_2}))
易得
(frac{a_0a_2}{b_1}>frac{a_0a_1}{b_2},frac{a_0a_2}{b_1}gefrac{a_0}{b_1})
所以把max((frac{a_0}{b_2},frac{a_0a_2}{b_1}))(ge)max((frac{a_0}{b_1},frac{a_0a_1}{b_2}))
所以把(a_2,b_2)放第2个位置答案才能最小
虽然只是证了两个数的情况
但是若有更多数a的乘积其实可以看做上述式子(a_0)
于是得到结论
把(a_i imes b_i)的值大的放后 答案才能最小
证毕
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#define inf 100000000
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
int n;
struct node
{
int a,b,ab;
}dg[1010];
const int p=1e4;
struct hact
{
int arr[1000],len;
hact()
{
memset(arr,0,sizeof(arr));
len=0;
}
void print()
{
printf("%d",arr[len]);
dwn(i,len-1,0)
{
printf("%04d",arr[i]);
}
putchar('
');
}
}ans,mul;
hact operator *(hact a,int b)
{
if(b==0)
{
hact c;
return c;
}
hact c;c.len=a.len;ll x=0;
rep(i,0,c.len)
{
c.arr[i]=(1ll*a.arr[i]*b+x)%p;
x=(1ll*a.arr[i]*b+x)/p;
}
while(x>0)
{
c.arr[++c.len]=x%p;
x/=p;
}
return c;
}
hact operator /(hact a,int b)
{
hact c;c.len=a.len;ll x=0;
dwn(i,c.len,0)
{
c.arr[i]=(a.arr[i]+x*p)/b;
x=(a.arr[i]+x*p)%b;
}
dwn(i,c.len,1)
{
if(c.arr[i]==0) c.len--;
else break;
}
return c;
}
hact arrmax(hact a,hact b)
{
if(a.len>b.len)
return a;
else if(a.len<b.len)
return b;
dwn(i,a.len,0)
{
if(a.arr[i]>b.arr[i]) return a;
else if(a.arr[i]<b.arr[i]) return b;
}
return a;
}
bool cmp(node a,node b)
{
return a.ab<b.ab;
}
int main()
{
scanf("%d",&n);
mul.arr[0]=1;
rep(i,0,n)
{
scanf("%d%d",&dg[i].a,&dg[i].b);
dg[i].ab=dg[i].a*dg[i].b;
mul=mul*dg[i].a;
}
sort(dg+1,dg+n+1,cmp);
dwn(i,n,1)
{
ans=arrmax(ans,mul/dg[i].ab);
mul=mul/dg[i].a;
}
ans.print();
return 0;
}