https://vjudge.net/problem/Kattis-playingwithnumbers
给定一群数。用 x y表示(这个数的值为2^x*3^y)
然后让你输出 m-1行。
第一行 没有gcd操作,有m-1个lcm操作
第二行 1个gcd操作,m-2个lcm操作
。。第m-1行 m-1个gcd操作 0个lcm操作
输出每行(对应情况)的 可能取的最大值,最小值。
仍用 x y 这种形式表示。
这道题我感觉难点在于 比较2^x1*3^y1 和2^x2*3^y2的大小。
但是我们知道了这个,,竟然没有做出来。。。。
本题中 数据范围很大。
并且发现 都是2^x*3^y的格式,这种格式保证了一点。
那就是 lcm两个数,就是两个数 再x和y的幂项上取最大。
而gcd呢,就是取最小。。(mdzz现在看起来感觉在情理之中)
当第一行时 ,只能等到最大值。
第二行, 最大值可以得到,最小值就是 最小的整体
中间情况,多可以得到最大值,最小值。
倒数第二行 ,最大值就是 整体最大(留这个整体最大的和其他lcm)
最小值 是可以得到的。
最后一行 ,只能得到最小值。
注意 当m==3时,m-1和2发生了重合。
当前情况下,和M-1行情况相同。 假设 x 为2的幂最大的数。
y为3的幂最大得数。 z为整体最大
那么 无疑 lcm(z,gcd(x,y)) 比gcd(lcm(x,y),z)要好。
#include <bits/stdc++.h>
using namespace std;
const int maxn=6e4+100;
struct Node{
int x,y;
}node[maxn];
bool cmp2(Node a, Node b)
{
return ( log(2) * a.x + log(3) * a.y) < (log(2) * b.x + log(3) * b.y);
}
int main()
{ int m;
while(~scanf("%d",&m)){
for(int i=1;i<=m;i++){
scanf("%d%d",&node[i].x,&node[i].y);
}
sort(node+1,node+m+1,cmp2);
int max1=-1;
int max2=-1;
int min1=1e7;
int min2=1e7;
for(int i=1;i<=m;i++){
max1=max(max1,node[i].x);
min1=min(min1,node[i].x);
max2=max(max2,node[i].y);
min2=min(min2,node[i].y);
}
if(m==1){
printf("%d %d %d %d\n",max1,max2,max1,max2);
}
else if(m==2){
printf("%d %d %d %d\n",max1,max2,max1,max2);
printf("%d %d %d %d\n",min1,min2,min1,min2);
}
else{
for(int i=1;i<=m;i++){
if(i==1)
printf("%d %d %d %d\n",max1,max2,max1,max2);
else if(i==m-1)
printf("%d %d %d %d\n",node[m].x,node[m].y,min1,min2);
else if(i==2)
printf("%d %d %d %d\n",max1,max2,node[1].x,node[1].y);
else if(i==m)
printf("%d %d %d %d\n",min1,min2,min1,min2);
else
printf("%d %d %d %d\n",max1,max2,min1,min2);
}
}
}
return 0;
}