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 }
View Code
原文地址:https://www.cnblogs.com/ww3113306/p/9880467.html