這道題首先應該理解題意:
題目給你n個商品的價格(並且各自的商品價格對於各自的座標從[1,n])說叫你自己去選擇一個順序,並且給你兩個條件:
1.給你x,a,x表示在位置a,2a,3a,4a…對應的商品價格爲pix%;
2.給你y,b,y表示在位置b,2b,3b…對應的商品價格爲piy%;
3.如果a,b的公倍數的位置,那麼對應的商品價格爲pi*(x+y)%;
4.其他位置對應商品價格爲pi0;
然後就是這個k的含義了;
k表示從下標1----k的位置對應的商品價格的總和就應該>=k,那麼這個k纔是滿足條件的;
然後讓我們求最小的k;如果沒有那麼就輸出-1;
好了,這道題就這樣理解到了;
然後怎麼寫呢?
首先肯定要輸入原價格;因爲有一個%,所以爲了避免浮點型,所以我就直接用ll了
然後在和k比較時,我就只需要比較k100;
這樣讀完題之後,應該可以想到,對應的位置的價格不應該是越大越好嗎?
所以每次我都去找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;
}