cf1073d Berland Fair
题解:
可以发现,每走完一圈付的钱和买的数量是有周期性的,即如果没有因为缺钱而买不起某家店的东西,那么这一圈的所以决策将会和上一圈相同,这个应该是很好理解的,想想就好了。
因为钱数固定时,决策固定,所以每次都O(n)扫一遍看当前情况下走一圈会花多少钱。
然后直接一直取这么多钱,直到钱不够为止,再进行下一次计算走一圈的钱数,显然用类似取模的东西可以解决。
为什么这样的复杂度是正确的呢?
一开始觉得是$n^2$的,还想了半天如何优化,但其实因为每次钱数都取了模,而一个数每次取模至少会减少一半,所以其实只会进行log次,所以复杂度是$nlogn$的
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 230000 5 #define LL long long 6 7 int n, top; 8 LL ans, t, minn = 10000000000000000LL; 9 LL s[AC]; 10 11 inline LL read() 12 { 13 LL x = 0;char c = getchar(); 14 while(c > '9' || c < '0') c = getchar(); 15 while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); 16 return x; 17 } 18 19 inline void upmin(LL &a, LL b){ 20 if(b < a) a = b; 21 } 22 23 void pre() 24 { 25 n = read(), t = read(); 26 for(R i = 1; i <= n; i ++) 27 s[i] = read(), upmin(minn, s[i]); 28 } 29 30 void work() 31 { 32 while(t >= minn) 33 { 34 LL tmp = t, rnt = 0; 35 for(R i = 1; i <= n; i ++) 36 if(tmp >= s[i]) tmp -= s[i], ++ rnt; 37 tmp = t - tmp;//获得实际消耗的钱 38 LL k = t / tmp; 39 ans += k * rnt; 40 t -= k * tmp; 41 } 42 cout << ans << endl; 43 } 44 45 int main() 46 { 47 // freopen("in.in", "r", stdin); 48 pre(); 49 work(); 50 // fclose(stdin); 51 return 0; 52 }