zoukankan      html  css  js  c++  java
  • D. Berland Fair (暴力出奇迹 + 时间复杂度证明)

    题目:传送门

    题意:有 n 个糖果,第 i 个糖果卖 ai 块钱,你现在有 T 块钱,你每次都从第一块糖果开始看,如果你的钱数够买当前的糖果,那么你就会花钱买它,如果你看完了所有 n 块糖果,那么你会从 1 重新开始看,直到你的钱数小于最便宜的糖果的价格。

    1 <= n <= 2e5, 1 <= ai <= 1e9, 1 <= T <= 1e18

     

    思路:直接暴力就行了。 最多跑 logT 次 for,那时间复杂度才 o(n*logT) 完全可接受。

    关于复杂度的证明:

      设 C 为这一轮能买的糖果的总价格, Tcur 为这一轮之前剩下的钱, Tnew 为买完这一轮剩下的钱。

      Tnew = Tcur % C, 故 Tnew < C 且 Tnew < Tcur - C, 那 Tnew < Tcur / 2

      那这样每次都至少缩小一倍, 那就最多 logT 次。

    #include <bits/stdc++.h>
    #define LL long long
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF INT_MAX
    #define inf LLONG_MAX
    #define PI acos(-1)
    using namespace std;
    
    const int N = 1e6 + 5;
    
    LL a[N];
    
    void solve() {
        int n; LL T;
        scanf("%d", &n);
        scanf("%lld", &T);
        LL mi = INF;
        rep(i, 1, n) {
            scanf("%lld", &a[i]);
            mi = min(mi, a[i]);
        }
        LL ans = 0;
        while(T >= mi) {
            LL sum = 0;
            LL c = 0;
            rep(i, 1, n) {
                if(T >= a[i]) {
                    sum += a[i];
                    T -= a[i];
                    ans++;
                    c++;
                }
            }
            LL tmp = T / sum;
            ans = ans + tmp * c;
            T %= sum;
        }
        printf("%lld
    ", ans);
    }
    
    int main() {
    
        solve();
    
        return 0;
    }
    一步一步,永不停息
  • 相关阅读:
    【动态规划】 EditDistance
    招聘
    算法01 C语言设计
    keras04
    电影《邪不压正》打动我的
    Eclipse
    6.面向对象编程(下)2
    获取一个1-100之间的随机数
    java如何使用帮助文档api
    3.java基础语法(下)
  • 原文地址:https://www.cnblogs.com/Willems/p/12388407.html
Copyright © 2011-2022 走看看