[codeforces][Educational Codeforces Round 53 (Rated for Div. 2)D. Berland Fair]
http://codeforces.com/problemset/problem/1073/D
题目大意:有n个物品(n<2e5)围成一个圈,你有t(t<1e18)元,每次经过物品i,如果身上的钱可以购买该物品就直接购买,直到一件物品都不能购买,求一共可以购买多少件物品.
题目分析:由于t的数量级达到了1e18,所以不可能直接进行暴力模拟,这个时候就要想到周期性地模拟.
题解:每次遍历一下1~n这n个物品,然后计算出可以取的物品数以及价值,然后用剩下的钱除以这个价值,得到可以进行的轮数,累加到结果中,然后继续遍历..继续累加...这个方法看起来还是很暴力,但是可以证明最多进行logTl轮,也就是总时间复杂度为O(N*logT).下面是轮数为logT的证明..
复杂度的证明:遍历之前的钱数记为Tcur,可以取走的物品价值记为C,遍历并且累加之后的钱数记为Tnex,则有Tnex=Tcur%C,则可以得到Tnex<C&&Tnex<=Tcur-C,所以Tnex<Tcur/2,所以可以得到能进行的轮数也就是logT,总的复杂度也就是O(N*logT)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 ll n,t,qwq[200005]; 8 ll minn=1e12; 9 int main(){ 10 //freopen("in.txt","r",stdin); 11 cin>>n>>t; 12 for(int i=0;i<n;i++){ 13 scanf("%lld",&qwq[i]); 14 minn=min(minn,qwq[i]); 15 } 16 ll ans=0; 17 while(t>=minn){ 18 ll k=0; 19 ll kk=0; 20 for(int i=0;i<n;i++){ 21 if(t>=qwq[i]){ 22 t-=qwq[i]; 23 k++; 24 kk+=qwq[i]; 25 } 26 } 27 ans+=k+(t/kk)*k; 28 t%=kk; 29 } 30 cout << ans << endl; 31 return 0; 32 }