C. Save the Nature(二分+貪心)

在這裏插入圖片描述在這裏插入圖片描述
這道題首先應該理解題意:
題目給你n個商品的價格(並且各自的商品價格對於各自的座標從[1,n])說叫你自己去選擇一個順序,並且給你兩個條件:
1.給你x,a,x表示在位置a,2a,3a,4a…對應的商品價格爲pix%;
2.給你y,b,y表示在位置b,2b,3b…對應的商品價格爲pi
y%;
3.如果a,b的公倍數的位置,那麼對應的商品價格爲pi*(x+y)%;
4.其他位置對應商品價格爲pi0;
然後就是這個k的含義了;
k表示從下標1----k的位置對應的商品價格的總和就應該>=k,那麼這個k纔是滿足條件的;
然後讓我們求最小的k;如果沒有那麼就輸出-1;
好了,這道題就這樣理解到了;
然後怎麼寫呢?
首先肯定要輸入原價格;因爲有一個%,所以爲了避免浮點型,所以我就直接用ll了
然後在和k比較時,我就只需要比較k
100;
這樣讀完題之後,應該可以想到,對應的位置的價格不應該是越大越好嗎?
所以每次我都去找1–k位置的和,並且把在位置[1,k]的商品儘量放在更大的對應的max(x,max(y,x+y))上,所以這樣就能使得儘可能大的價格被出售;
關鍵是我怎麼去定這個k呢?
因爲一共只有n個位置,所以我只需要二分查找個k就可以了;
如果求出來的前mid個的sum>=k那麼就表明這個k是存在的;那麼就r=mid-1;
如果求出來的前mid個的sum<k,那麼就表明這個k需要往上擴大,才能使得更多的商品被加進來;
所以二分的思想就是這樣滴;
AC代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
vector<ll> q1;
vector<ll> q2;
ll n,x,y,a,b,k;//全局變量
ll l=1,r=n;
ll ans=0;
ll mid;
ll gcd(ll a,ll b){
   return b?gcd(b,a%b):a;
}
bool cmp(ll a,ll b){return a>b;}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
       q1.clear();
        scanf("%lld",&n);
        for(int i=1;i<=n;i++){
            ll t;
            scanf("%lld",&t);
            q1.push_back(t);//避免精度
        }
        scanf("%lld %lld %lld %lld %lld",&x,&a,&y,&b,&k);
        ll gc=gcd(a,b);//求最大公約數
        ll lcm=a*b/gc;//求他們的最小公倍數,如果是lcm的倍數,那麼肯定就是a,b的倍數
       sort(q1.begin(),q1.end(),cmp);//排序
       l=1,r=n;//二分區間
        ans=0;
       while(l<=r){
                 q2.clear();
            mid=(l+r)/2;
            for(int j=1;j<=mid;j++){//找[1,mid]區間的對應位置的比例價格值
             if(j%lcm==0){
                q2.push_back(x+y);
             }else if(j%a==0){
                q2.push_back(x);
             }else if(j%b==0){
                q2.push_back(y);
              }
            }

            ll res=0;
            sort(q2.begin(),q2.end(),cmp);
            for(int i=0;i<q2.size();i++){//這裏就用了貪心思想,把對應max(x,max(y,x+y))*對應價格對大值,因爲題目說了可以任意排序
                res+=q1[i]*q2[i];
            }
           if(res>=k*100){//如果比k*100大,那麼就要縮小右區間
              r=mid-1;
              ans=mid;//記錄答案
           }else{
              l=mid+1;
           }

       }
//       cout<<"f"<<endl;
       if(!ans)printf("-1\n");//判斷是否ans存在
       else printf("%lld\n",ans);
    }

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章