题目链接:https://www.acwing.com/problem/content/description/116/
证明转载于https://www.acwing.com/problem/content/description/116/
使用“轻微扰动”的方法判断当前的选择是否是最优的,我们可以从中看到,减少逆序对的数量不会使结果更差,增加逆序对的数量不会使得结果更好,所以按照冒泡排序的思想,可以通过相邻项交换来使最大值最小。由于乘积可能达到1e4000,所以使用高精度进行处理。
代码如下:
#include<iostream> #include<vector> #include<algorithm> using namespace std; #define maxn 1005 struct node{ int a,b; bool operator < (const node& other)const { return a*b<other.a*other.b;//按照贪心策略进行排序 } }p[maxn]; vector<int> mul(vector<int> a,int b){//大整数存储在vector中,a*b vector<int> c; int t=0; for(int i=0;i<a.size();i++){ t+=a[i]*b; c.push_back(t%10); t/=10;//进位 } while(t){//将剩余进位压入vector c.push_back(t%10); t/=10; } return c; } vector<int> div(vector<int> a,int b){//大整数与一个int整数相除取整 vector<int> c; bool is_first=true;//除法的结果是从第一个有效位开始存储的 int t=0; for(int i=a.size()-1;i>=0;i--){//模拟除法,从最高位开始计算 t=t*10+a[i]; int x=t/b; if(!is_first || x){//第一个非零的数为有效位数,或者不是第一个数,都是有效位数 is_first=false; c.push_back(x); } t%=b;//余数参与下一轮计算 } reverse(c.begin(),c.end());//除数的计算中数字出现顺序是颠倒的 return c; } vector<int> max_vec(vector<int> a,vector<int> b){//返回较大的大数 if(a.size()>b.size())return a; if(a.size()<b.size())return b; // 两个vector位数相同就从最高位开始逐个位数比较 if(vector<int>(a.rbegin(),a.rend()) > vector<int>(b.rbegin(),b.rend()))return a; return b; } int main (){ int n; cin>>n; for(int i=0;i<=n;i++)scanf("%d%d",&p[i].a,&p[i].b);//最前面的国王也算一个 sort(p+1,p+n+1); vector<int> product(1,1);//累乘的基数,存放了一个1 vector<int> res(1,0);//存放的是最大的金币数,也就是结果 for(int i=0;i<=n;i++){ if(i)res=max_vec(res,div(product,p[i].b));//前面A的前缀积除以b product=mul(product,p[i].a); } for(int i=res.size()-1;i>=0;i--)cout<<res[i]; cout<<endl; return 0; }