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\n");
        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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM