1. 程式人生 > >[codeforces][Educational Codeforces Round 53 (Rated for Div. 2)D. Berland Fair]

[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)

 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 }
View Code