【洛谷P1080】国王游戏
[NOIP2012 提高组] 国王游戏
题目描述
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
输入格式
第一行包含一个整数 n,表示大臣的人数。
第二行包含两个整数 a 和 b,之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。
输出格式
一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。
样例 #1
样例输入 #1
3
1 1
2 3
7 4
4 6
样例输出 #1
2
【数据范围】
对于 20% 的数据,有 1≤ n≤ 10,0 < a,b < 8;
对于 40% 的数据,有 1≤ n≤20,0 < a,b < 8;
对于 60% 的数据,有 1≤ n≤100;
对于 60% 的数据,保证答案不超过 10^9;
对于 100% 的数据,有 1 ≤ n ≤1,000,0 < a,b < 10000。
今天写了洛谷的P1080
没错
一道贪心题
其实邻项交换在lyd《算法竞赛进阶指南》里读到过了
推导就不说了 跟丘砖逆序对那章有点神似(?
但是写该死的高精还是花了好久
看代码吧
高精的题目看来得多练 不然上考场老是出事
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
int l,r;
};
node q[1005];
int n,sx,sy,len,f,maxxlen;
int a[10005],tem[10005],fa[10005],maxx[10005];//这里s和a解出来都是反的sx 用于乘法的简便 而fa才是真正的sx 用于除法的简便
char s[10005];
bool cmp(node x,node y){
if(x.l*x.r==y.l*y.r) return x.r<y.r;
else return x.l*x.r<y.l*y.r;
}
void mult(int a[],int b){//高精乘低精的模板题
memset(tem,0,sizeof(tem));
for(int i=1;i<=len;i++) tem[i]=a[i]*b;
for(int i=1;i<=len;i++){
if(tem[i]/10){
tem[i+1]+=tem[i]/10;
tem[i]%=10;
}
while(tem[len+1]) len++;
while(tem[len]/10){
tem[len+1]+=tem[len]/10;
tem[len]%=10;
len++;
}//这堆要放在括号里面 这样好像比较严谨(?) 反正模版也是拿来背的
}
for(int i=1;i<=len;i++) a[i]=tem[i];
}
void divv(int a[],int b){//高精除低精以及两个高精数的比较
memset(tem,0,sizeof(tem));
int x=0;
for(int i=1;i<=len;i++){
tem[i]=(x*10+a[i])/b;
x=(x*10+a[i])%b;
}//正常高精除低精的除法
int pd=0;
for(int i=1;i<=len;i++){
if(tem[i]){
pd=1;
f=i-1;
break;
}
}//去除前导零
if(pd){
for(int i=f+1;i<=len;i++){
if(len-f<maxxlen){
break;
}
if(len-f>maxxlen){
for(int j=f+1;j<=len;j++){
maxx[j]=tem[j];
}
maxxlen=len-f;
break;
}
if(len-f==maxxlen&&tem[i]>maxx[i]){
for(int j=f+1;j<=len;j++){
maxx[j]=tem[j];
}
maxxlen=len-f;
break;
}
if(len-f==maxxlen&&tem[i]<maxx[i]){
break;
}
}
}//比较maxx和tem的大小
}
int main(){
scanf("%d",&n);
scanf("%d%d",&sx,&sy);
for(int i=1;i<=n;i++){
scanf("%d%d",&q[i].l,&q[i].r);
}
sort(q+1,q+1+n,cmp);
for(int i=0;sx;i++){
s[i]=sx%10+'0';
sx/=10;
}
len=strlen(s);
for(int i=1;i<=len;i++) a[i]=s[i-1]-'0';
for(int i=1;i<=len;i++) fa[i]=s[len-i]-'0';
for(int i=1;i<=n;i++){
divv(fa,q[i].r);
mult(a,q[i].l);//这里乘除的次序要注意一下
for(int j=1;j<=len;j++) fa[j]=a[len+1-j];
}
int pd=0;
for(int i=f+1;i<=maxxlen+f;i++){
if(maxx[i]){
pd=1;break;
}
}
if(pd==0){
cout<<0;
system("pause");
return 0;
}//如果最后结果是0的话得特判 不然下面输出不了
for(int i=f+1;i<=maxxlen+f;i++) cout<<maxx[i];
system("pause");
return 0;
}

浙公网安备 33010602011771号