zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 90 (Rated for Div. 2) 题解A~F

    A: 

    现有两种购物方式 1.花单价a元购买  2.花c元购买b个物品    给出数据后问 1.购买多少个物品可以使得用方式1的花费严格小于方式2        2.购买多少个物品可以使得用方式2的花费严格小于方式1

    若不存在输出-1

    直接贪心  由于b>=2 ,购买一个必然是最优,如果这都不行那更大也不行   第二个询问也是同理 ,因此只需特判

    CODE:

    int main() {
        int  T;
        ll  a, b, c;
        scanf("%d", &T);
        while (T--) {
            ll ans1, ans2;
            scanf("%lld%lld%lld", &a, &b, &c);
            if (b != 1) {
                if (a < c) ans1 = 1;
                else ans1 = -1;
            }
            else {
                if (a < c) ans1 = 1;
                else ans1 = -1;
            }
            if (b * a <= c) ans2 = -1;
            else ans2 = b;
            printf("%lld %lld\n", ans1, ans2);
        }
    }
    View Code

    B:

    给定一个01串,两人开始删串,每次可以删除“01” 或者“10” 最后不能删的人输。

    显然,最终若全是1或者全是0或者空者输,因此可直接根据个数判断

    CODE:

    string s;
     
    int main() {
        int T;
        cin >> T;
        while (T--) {
            cin >> s;
            int l1, l2;
            l1 = l2 = 0;
            for (int i = 0; i < s.length(); i++) {
                if (s[i] == '1') l1++;
                else l2++;
            }
            if (min(l1, l2) & 1) puts("DA");
            else puts("NET");
        }
        return 0;
    }
    View Code

    C:

    讲道理,此题不太懂在干什么,当时就照着这段代码模拟整合了一下,用到了前缀和 。 注意开longlong!!!

    CODE;

    string s;
    ll v[maxn];
     
     
    int main() {
        int T;
        cin >> T;
        while (T--) {
            memset(v,0,sizeof v);
            cin >> s;
            ll res = 0;
            int tag = 0;
            for (ll i = 0; i < s.length(); i++) {
                if (s[i] == '+') v[i]++;
                else v[i]--;
                if (i) v[i] += v[i - 1];
                if (v[i] < 0 && v[i] == tag -1) {
                    tag--;
                    res += i + 1;
                }
            }
            res+=(ll)s.length();
            cout << res << endl;
        }
    }
    View Code

    D:

    给定数组a, 你可以进行一次操作来翻转区间,问最终所有偶数位的最大和 。 下标从0开始。 

    当时其实已经做出来了,但是没判断vector为空导致最后几分钟没AC,懊悔不已。

    考虑到有效的翻转其实就是选定一个端点为偶一个为奇数。 这样做的效果其实就是把这段区间的偶数位全部换成奇数位。

    因此只要求出整段的最大差(利用差分),再加上原来的偶数位的和即可。 最大差只需跑一遍最大子段和。 注意从左往右和从右往左都跑一遍。开longlong

    CODE:

    ll a[maxn];
    vector<ll> v1;
    vector<ll> v2;
     
    ll solve1() {
        if(v1.empty()) return 0;
        ll tmp = 0;
        ll now = v1[0];
        ll ans = now;
        if (now > 0) tmp = now;
        for (int i = 1; i < v1.size(); i++) {
            tmp += v1[i];
            if (tmp > ans) ans = tmp;
            if (tmp < 0) tmp = 0;
        }
        return max(0ll, ans);
    }
    ll solve2() {    
        if(v2.empty()) return 0;
        ll tmp = 0;
        ll now = v2[0];
        ll ans = now;
        if (now > 0) tmp = now;
        for (int i = 1; i < v2.size(); i++) {
            tmp += v2[i];
            if (tmp > ans) ans = tmp;
            if (tmp < 0) tmp = 0;
        }
        return max(0ll, ans);
    }
     
    int main() {
        int T;
        int n;
        scanf("%d", &T);
        while (T--) {
            v1.clear();
            v2.clear();
            ll res = 0;
            scanf("%d", &n);
            if(n==1){
                int tmp;
                scanf("%d",&tmp);
                printf("%d\n",tmp);
                continue;
            }
            ll res1, res2;
            res1 = res2 = 0;
            //int Max = 0;
            for (int i = 0; i < n; i++) {
                scanf("%lld", &a[i]);
                if (i & 1) res2 += a[i];
                else res1 += a[i];
                if (i%2) v1.push_back(a[i]-a[i-1]);
            }
            for (int i = 0; i < n; i++) {
                 if (i%2 && i < n-1) v2.push_back(a[i]-a[i+1]);
            }
            res = max(solve1(),solve2());
            printf("%lld\n", res1 + res);
        }
    }
    View Code

    E:

    令f(X) 为X的各个位数之和。给定n,k  求出最小的X使得 ( sigma(f(x+i)) i=0~k ) = n 。

    此题比较综合,思路和实现其实都不好想。 

    思路:最后变动的位数其实只有最后一位。所有其实可以考虑枚举最后一位。 由于希望X尽量小,我们自然希望中间用9填充,故可枚举中间9的个数,前面的数越小越好。

    细节:考虑进位带来的影响。

    CODE:

    int get_sum(int s, int cnt) {
        int res = 0;
        for (int i = 0; i < cnt; i++) res += (s + i) % 10;
        return res;
    }
    
    inline void upd(string& have, const string& s) {
        if (have == "-1") have = s;
        else if (have.size() > s.size()) have = s;
        else if (have.size() == s.size() && have > s) have = s;
    }
    
    string get(int need) {
        string res = "";
        if (need >= 9) res.push_back('8'), need -= 8;
        while (need >= 10) res.push_back('9'), need -= 9;
        if (need > 0) res.push_back('0' + need);
        reverse(res.begin(), res.end());
        return res;
    }
    
    string solve(int n, int k) {
        k++;
        string best = "-1";
        for (int s = 0; s <= 9; s++) {
            int need = n - get_sum(s, k);
            if (need < 0) continue;
            int l = min(k, 10 - s);
            int r = k - l;
            for (int c = 0; c < 20; c++) {
                int t = 9 * c;
                int tmp = need - l * t - r;
                if (tmp >= 0 && tmp % k == 0) {
                    string cur = get(tmp / k);
                    upd(best, cur + string(c, '9') + string(1, '0' + s));
                }
            }
        }
        return best;
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        while (T--) {
            int n, k;
            scanf("%d%d", &n, &k);
            cout << solve(n, k) << endl;
        }
    }
    View Code

    F:

    n个家庭成一个环  给定数组a,b  对于每个i,可以分bi给第i个家庭或第 i+1个家庭 问能否使得每个家庭最终大于等于ai

    首先这个问题是环,考虑先退化成链来考虑,问题就简化许多。 只需二分第一个家庭失去的b的大小,结果就呈现出单调性。只有此时得到的最小解就有可能是答案。因此只需最后再judge一遍即可。

    CODE:

    int a[maxn], b[maxn];
    int r[maxn];
    int n;
    
    bool check(int x) {
        r[0] = b[0] - x;
        for (int i = 1; i < n; i++) {
            r[i] = b[i] - max(0, a[i] - r[i-1]);
            if (r[i] < 0) return false;
        }
        return true;
    }
    
    
    bool Check(int x) {
        r[0] = b[0] - x;
        for (int i = 1; i < n; i++) {
            r[i] = b[i] - max(0, a[i] - r[i - 1]);
            if (r[i] < 0) return false;
        }
        return (r[n - 1] + x >= a[0]);
    }
    
    
    bool solve() {
        scanf("%d", &n);
        for (int i = 0; i < n; i++) scanf("%d", a + i);
        for (int i = 0; i < n; i++) scanf("%d", b + i);
        int l = 0, r = b[0];
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (check(mid)) l = mid;
            else r = mid - 1;
        }
        if (Check(l)) return true;
        else return false;
    }
    
    
    
    int main() {
        int T;
        scanf("%d", &T);
        while (T--) {
            if (solve()) puts("YES");
            else puts("NO");
        }
    }
    View Code

       

  • 相关阅读:
    观众查询界面
    排球积分程序
    产品会议
    本周工作量及进度统计
    排球积分规则
    我与计算机
    排球记分员
    怎样成为一个高手观后感
    第十八周冲刺
    十六周
  • 原文地址:https://www.cnblogs.com/hznumqf/p/13196646.html
Copyright © 2011-2022 走看看