zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 86 (Rated for Div. 2)

    题目传送门

    A. Road To Zero

    两个数,将其中一个增加或减少1的代价为a,同时增加或减少1的代价为b,求将两个数同时变为0的最小代价。

    当一个数为0或者两个数异号时,最优为只执行代价为a的操作,当两个数同号时,要考虑b与a*2的大小。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    ll x, y, a, b;
    
    int main()
    {
        int t;
        cin >> t;
        while (t--)
        {
            cin >> x >> y;
            cin >> a >> b;
            if (b > a * 2 || x * y <= 0)
                cout << (abs(x) + abs(y)) * a << endl;
            else
            {
                x = abs(x);
                y = abs(y);
                cout << min(x, y) * b + abs(y - x) * a << endl;
            }
        }
    }
    View Code

    B. Binary Period

    利用字符串t构造s使t为s的一个子序列,并且使周期k最小,长度不大于t的两倍。

    根据题意这样构造出来k只能是1或2。如果t本身具有周期1,直接输出,否则可以在两个相同元素中间插另一个元素,此时s周期为2。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    int n;
    char s[110];
    
    int main()
    {
        int t;
        cin >> t;
        while (t--)
        {
            memset(s, 0, sizeof(s));
            cin >> s;
            n = strlen(s);
            int flag = 1;
            rep(i, 1, n - 1) if (s[i] != s[i - 1])
                flag = 0;
            if (flag)
                cout << s;
            else
                rep(i, 0, n - 1)
                {
                    cout << s[i];
                    if (s[i] == s[i + 1])
                        putchar(s[i] == '0' ? '1' : '0');
                }
            cout << endl;
        }
    }
    View Code

    C. Yet Another Counting Problem

    x∈[l,r], ((x mod a) mod b)≠((x mod b) mod a) 的个数。

    考虑预处理前缀和,但是l,r实在是太大了。发现x变化具有周期性,周期为a*b,只用预处理[0,a*b]即可。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    ll a, b, q, num[40010];
    ll l, r, ans;
    int main()
    {
        int t;
        cin >> t;
        while (t--)
        {
            cin >> a >> b >> q;
            rep(i, 1, a * b)
            {
                num[i] = (i % a % b != i % b % a) ? 1 : 0;
                num[i] += num[i - 1];
            }
            while (q--)
            {
                cin >> l >> r;
                ans = (r - l) / (a * b) * num[a * b];
                l %= (a * b);
                r %= (a * b);
                if (r >= l)
                    cout << ans + num[r] - num[l - 1] << " ";
                else
                    cout << ans + num[r] + num[a * b] - num[l - 1] << " ";
            }
            cout << endl;
        }
    }
    View Code

    D. Multiple Testcases

    比赛时读了好久才明白题意(wtcl),组合m数组,在满足条件的情况下使ans(组合的数量)最小,条件为一个组合中大于等于i的数不超过c[i]个。

    ans挺好找。然后每个组合的元素,按照m[i]从大到小往里面填就行了。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    ll n, k, m[200010], c[200010];
    ll ans;
    vector<ll> tmp[200010];
    int main()
    {
        cin >> n >> k;
        rep(i, 1, n) cin >> m[i];
        rep(i, 1, k) cin >> c[i];
        sort(m + 1, m + n + 1);
        for (int i = n; i; i--)
        {
            if (m[i] == m[i - 1])
                continue;
            ans = max(ans, (ll)ceil(1.0 * (n - i + 1) / c[m[i]]));
        }
        for (int i = n, j = 0; i; i--, j = (j + 1) % ans)
            tmp[j].push_back(m[i]);
        cout << ans << endl;
        rep(i, 0, ans - 1)
        {
            int j = tmp[i].size();
            cout << j << " ";
            rep(z, 0, j - 1) cout << tmp[i][z] << " ";
            cout << endl;
        }
    }
    View Code

    E. Placing Rooks

    n*n的格子放n个车,要求所有空格子都在攻击范围、k对车能互相攻击。

    所有格子都在攻击范围,那么每一行 / 每一列都要有车。

    k对车能相互攻击,那么要空k列不能放车(保证每一行都有一辆车),或者空k行不放车(保证每一列都有车)。

    先计算行,问题相当于在n-k列中放n个车,答案为

    至于为什么是这样计算可以先学习特斯林数和“n个球m个盒子问题”。

    当k==0的时候行和列的答案重复了,所以k!=0的时候答案乘2。k>=n时答案为0。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    const int mod = 998244353;
    ll n, k;
    ll ans;
    ll fac[200010];
    
    ll ksm(ll a, ll b)
    {
        ll res = 1;
        for (; b; b >>= 1, a = a * a % mod)
            if (b & 1)
                res = res * a % mod;
        return res;
    }
    
    ll C(ll x, ll y)
    {
        return fac[x] * ksm(fac[y] * fac[x - y] % mod, mod - 2) % mod;
    }
    
    int main()
    {
        fac[0] = 1;
        cin >> n >> k;
        rep(i, 1, n) fac[i] = fac[i - 1] * i % mod;
        if (k >= n)
        {
            puts("0
    ");
            return 0;
        }
        rep(i, 0, n - k)
        {
            ll flag = i & 1 ? -1 : 1;
            ll tmp = flag * (C(n - k, i) * ksm(n - k - i, n) % mod);
            ans = (ans + tmp + mod) % mod;
        }
        if (k == 0)
            cout << ans << endl;
        else
            cout << (ans * C(n, n - k) % mod) * 2 % mod << endl;
    }
    View Code
  • 相关阅读:
    网速问题?更换国内源吧!
    NES像素风格的Raspberry
    dalao自动报表邮件2.0
    大佬要我写自动邮件报表系统
    扬帆起航
    Linux下安装与配置tomcat集群+负载均衡
    centos配置ssh和ftp服务
    tomcat中server.xml配置详解
    设置windows 宿主计算机和VMware虚拟机共享文件夹
    Redhat6 yum 安装与配置
  • 原文地址:https://www.cnblogs.com/likunhong/p/12784805.html
Copyright © 2011-2022 走看看