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:

Educational Codeforces Round 90 (Rated for Div. 2) 题解A~F_第1张图片

 

讲道理,此题不太懂在干什么,当时就照着这段代码模拟整合了一下,用到了前缀和 。 注意开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 v1;
vector 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

 

   

你可能感兴趣的:(Educational Codeforces Round 90 (Rated for Div. 2) 题解A~F)