《算法竞赛进阶指南》0x07 贪心 NOIP2012 vector模拟高精度计算

题目链接: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; 
} 

 

posted @ 2020-06-16 11:16  WA自动机~  阅读(239)  评论(0编辑  收藏  举报