P1080 国王游戏 高精度【1】

本文解析了NOIP2012提高组的第二题,设计了一个有奖游戏算法,通过重新排列大臣的顺序,使得获得奖赏最多的大臣所获奖赏尽可能的少。使用了自定义的BigInteger类来处理大数运算,确保了在大量数据输入下,计算的准确性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述https://www.luogu.org/problemnew/show/P1080

恰逢 H国国庆,国王邀请n位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

输入输出格式

输入格式:

第一行包含一个整数n,表示大臣的人数。

第二行包含两个整数 a和 b,之间用一个空格隔开,分别表示国王左手和右手上的整数。

接下来 n行,每行包含两个整数a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。

输出格式:

一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

输入输出样例

输入样例#1: 复制

3 
1 1 
2 3 
7 4 
4 6 

输出样例#1: 复制

2

说明

【输入输出样例说明】

按1、2、3 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按 1、3、2 这样排列队伍,获得奖赏最多的大臣所获得金币数2;

按 2、1、3 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按2、3、1这样排列队伍,获得奖赏最多的大臣所获得金币数为9;

按 3、1、2这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按3、2、1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9。

因此,奖赏最多的大臣最少获得 2个金币,答案输出 2。

【数据范围】

对于 20%的数据,有 1≤ n≤ 10,0 < a,b < 81≤n≤10,0<a,b<8;

对于 40%的数据,有1≤ n≤20,0 < a,b < 81≤n≤20,0<a,b<8;

对于 60%的数据,有 1≤ n≤1001≤n≤100;

对于 60%的数据,保证答案不超过 10^9109;

对于 100%的数据,有 1 ≤ n ≤1,000,0 < a,b < 100001≤n≤1,000,0<a,b<10000。

NOIP 2012 提高组 第一天 第二题

#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;

struct BigInteger {
	typedef unsigned long long LL;

	static const int BASE = 100000000;
	static const int WIDTH = 8;
	vector<int> s;

	BigInteger& clean() {
		while(!s.back()&&s.size()>1)s.pop_back();
		return *this;
	}
	BigInteger(LL num = 0) {
		*this = num;
	}
	BigInteger(string s) {
		*this = s;
	}
	BigInteger& operator = (long long num) {
		s.clear();
		do {
			s.push_back(num % BASE);
			num /= BASE;
		} while (num > 0);
		return *this;
	}
	BigInteger& operator = (const string& str) {
		s.clear();
		int x, len = (str.length() - 1) / WIDTH + 1;
		for (int i = 0; i < len; i++) {
			int end = str.length() - i*WIDTH;
			int start = max(0, end - WIDTH);
			sscanf(str.substr(start,end-start).c_str(), "%d", &x);
			s.push_back(x);
		}
		return (*this).clean();
	}


	BigInteger operator * (const BigInteger& b) const {
		int i, j;
		LL g;
		vector<LL> v(s.size()+b.s.size(), 0);
		BigInteger c;
		c.s.clear();
		for(i=0; i<s.size(); i++) for(j=0; j<b.s.size(); j++) v[i+j]+=LL(s[i])*b.s[j];
		for (i = 0, g = 0; ; i++) {
			if (g ==0 && i >= v.size()) break;
			LL x = v[i] + g;
			c.s.push_back(x % BASE);
			g = x / BASE;
		}
		return c.clean();
	}
	BigInteger operator / (const BigInteger& b) const {
		//assert(b > 0);  // 3yêy±?D?′óóú0
		BigInteger c = *this;      
		BigInteger m;               
		for (int i = s.size()-1; i >= 0; i--) {
			m = m*BASE + s[i];
			c.s[i] = bsearch(b, m);
			m=m-b*c.s[i];
		}
		return c.clean();
	}

	BigInteger operator - (const BigInteger& b) const {
		//assert(b <= *this); // ??êy2??ü′óóú±???êy
		BigInteger c;
		c.s.clear();
		for (int i = 0, g = 0; ; i++) {
			if (g == 0 && i >= s.size() && i >= b.s.size()) break;
			int x = s[i] + g;
			if (i < b.s.size()) x -= b.s[i];
			if (x < 0) {
				g = -1;
				x += BASE;
			} else g = 0;
			c.s.push_back(x);
		}
		return c.clean();
	}

	int bsearch(const BigInteger& b, const BigInteger& m) const {
		int L = 0, R = BASE-1, x;
		while (1) {
			x = (L+R)>>1;
			if (b*x<=m) {
				if (b*(x+1)>m) return x;
				else L = x;
			} else R = x;
		}
	}

	bool operator >(const BigInteger& b) const {
		return b < *this;
	}

	bool operator<=(const BigInteger& b) const {
		return !(b < *this);
	}
	bool operator < (const BigInteger& b) const {
		if (s.size() != b.s.size()) return s.size() < b.s.size();
		for (int i = s.size()-1; i >= 0; i--)
			if (s[i] != b.s[i]) return s[i] < b.s[i];
		return false;
	}
	BigInteger operator + (const BigInteger& b) const {
		BigInteger c;
		c.s.clear();
		for (int i = 0, g = 0; ; i++) {
			if (g == 0 && i >= s.size() && i >= b.s.size()) break;
			int x = g;
			if (i < s.size()) x += s[i];
			if (i < b.s.size()) x += b.s[i];
			c.s.push_back(x % BASE);
			g = x / BASE;
		}
		return c;
	}
};

ostream& operator << (ostream& out, const BigInteger& x) {
	out << x.s.back();
	for (int i = x.s.size()-2; i >= 0; i--) {
		char buf[20];
		sprintf(buf, "%08d", x.s[i]);
		for (int j = 0; j < strlen(buf); j++) out << buf[j];
	}
	return out;
}
 
istream& operator >> (istream& in, BigInteger& x) {
	string s;
	if (!(in >> s)) return in;
	x = s;
	return in;
}




#define ll BigInteger
typedef struct {
	int l;
	int r;
    int res;
} Node;
Node a[1010];
bool mycmp(Node a,Node b) {
	//if(a.r!=b.r) return a.r<b.r;
	//else 
	return a.res<b.res;
}
int main() {
	int n;
	cin>>n;
	ll imax=0;
	for(int i=0; i<=n; i++)
		{
		  scanf("%d %d",&a[i].l,&a[i].r);	
		  a[i].res=a[i].l*a[i].r;
		}
	sort(a+1,a+n+1,mycmp);
	ll temp,t;
	t=a[0].l;
	for(int i=1; i<=n; i++) {
		temp=t/a[i].r;
		if(imax<temp)
		imax=temp;
		t=t*a[i].l;
	}
	cout<<imax<<endl;
	return 0;
}

别人的代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define FT(A,B,C) for(int A=B;A <= C;A++)
using namespace std;
const int N = 100005;
struct minister{
    int l,r,rank;
    //这里通过rank来确定大臣们的顺序 也就是贪心的部分
//    若 a[i].l / a[j].r < a[j].l / a[i].r 可以判断 i 放在 j 的前面可以使答案更小 
//       a[i].l * a[i].r < a[j].l * a[j].r(上式化简) 
    minister(){    }//没有这行会报错 
    minister(int a,int b):l(a),r(b),rank(a*b){    } //结构体的初始化 
    bool operator <(const minister &x)const{ return rank < x.rank; }// 定义一下大小规则
    //等会直接 sort 
}a[N];
struct int_l {
    int data[N];
    int_l() {//初始化 
        memset(data, 0, sizeof(data));
        data[0] = 1;
    }
    int_l(int x) {//用低精数 初始化(赋值) 高精数 
        memset(data, 0, sizeof(data));
        data[0] = 1;
        int i = 1;
        while (x) {
            data[i++] = x % 10;
            x /= 10;
        }
        data[0] = --i;// 这里位数不能错 
    }
    int_l operator *(const int &x) {//很普通的重载 *号 
        int_l a;
        int len;
        a.data[0] = data[0];
        FT(i, 1, data[0]) a.data[i] = data[i] * x;
        for (int i = 1; i <= a.data[0] || a.data[i]; len = ++i) {
            a.data[i + 1] += a.data[i] / 10;
            a.data[i] %= 10;
        }
        a.data[len] ? a.data[0] = len : a.data[0] = --len;
        return a;
    }
    int_l operator /(const int &x) { //高精除低精 
        int_l a;
        a.data[0]=data[0];
        int rest = 0;
        for (int i = data[0]; i >= 1; i--) { //注意要从最高位开始模拟 
            rest = rest * 10 + data[i];
            a.data[i] = rest / x;
            rest %= x;
        }
        while (!a.data[a.data[0]] && a.data[0]>1) a.data[0]--; //去掉多余的 0 
        return a;
    }
    bool operator <(const int_l &x)const{// 重载 <号 
        if(data[0]==x.data[0]){ //从位数开始比较 
            int i;
            for(i=data[0];data[i]==x.data[i] && i > 1;i--);//然后是最高位 
            if(i >= 1) return data[i] < x.data[i];
            else return false;
        }
        else return data[0] < x.data[0];
    }
};
ostream& operator << (ostream& out, const int_l &x) {
    FT(i, 1, x.data[0]) out << x.data[x.data[0] - i + 1];
    return out;
}

int n, x, y;
int_l ans;
//int_l X,Y; 
int main() {
//    while (1){  Debug
//        int x,y;
//        cin >> x >> y;
//        X = x;
//        Y = y;
//        cout << (X*y) << endl;
//        cout << (X / y) << endl;
//        cout << (X < Y) << endl;
//    }     
    ios::sync_with_stdio(false);
    cin>>n;
    FT(i,0,n){
        cin>>x>>y;
        a[i]=minister(x,y);
    }
    sort(a+1,a+n+1);
    int_l k(1);
    FT(i,1,n){//很简单的模拟 
        if(a[i-1].l==0) break;//判 0 
        k=k*a[i-1].l;
        int_l temp;// 注意被除数用temp 存下来
        //如有大臣 防止商为0 后 k无法更新 
        temp=k/a[i].r;
        if(ans<temp) ans=temp;
    }
    cout<<ans<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值