题意:n个数排成一个圆盘,一个人有T元钱,从第一个开始,只要他能买的,他一定会买,这样依次循环,直到他的钱不能买任何物品时结束,问,他能买多少件东西。
思路:按题意模拟即可,不过T太大,考虑优化,优化的方法是当n个数的最大值都比T小,并且n个数的sum也小于T时,我们直接一次性买n个即可。
当最大值大于T时,显然这个物品永远都不会被买到,直接丢弃即可。
最后一种情况,当最大值小于T,但是sum大于T时,直接O(n)模拟买一次即可。
具体实现利用multiset来维护,很方便。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
int n;
ll a[maxn];
ll T;
multiset<ll> se;
multiset<ll>::iterator it;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
//scanf("%d",&n,&T);
cin>>n>>T;
ll sum=0;
for(int i=1;i<=n;i++)
{
//scanf("%lld",a[i]);
cin>>a[i];
sum+=a[i];
// printf("%lld\n",a[i]);
se.insert(-a[i]);
}
//printf("11\n");
ll ans=0;
while(T>0&&se.size())
{
it=se.begin();
//printf("%d %lld\n",T,sum);
// cout<<T<<" "<<sum<<endl;
if(abs(*it)<=T&&sum<=T)
{
//cout<<1<<endl;
ll tmp=T/sum;
T-=tmp*sum;
ans+=tmp*se.size();
}
else if(abs(*it)<=T&&sum>T)
{
for(int i=1;i<=n;i++)
{
if(se.find(-a[i])==se.end()) continue;
if(a[i]<=T)
{
T-=a[i];
ans++;
}
if(T<0) break;
}
}
else
{
//cout<<2<<endl;
ll tmpp=*it;
se.erase(it);
sum+=tmpp;
}
}
printf("%lld\n",ans);
return 0;
}