Codeforces Round 957 (Div. 3)

Sakura17發表於2024-07-16

題目連結:Codeforces Round 957 (Div. 3)

總結:E不懂,F差一個set去重

A. Only Pluses

fag:列舉

B. Angry Monk

fag:模擬

Solution:分裂的花費為\(a_i - 1\),新增的花費為\(a_i\)

C. Gorilla and Permutation

fag:思維

Solution:大於等於\(k\)的數,逆序放在最前面,小於等於\(m\)的數,從最後面開始從大到小放,中間的位置任意放剩下的數。

void solve(){
    cin >> n >> m >> k;
    vector<int> a(n + 1);
    int i, l, r;
    
    for (i = n, l = 1; i >= k; i --, l ++)
        a[l] = i;
    
    for (i = m, r = n; i >= 1; i --, r --)
        a[r] = i;
    
    for (int i = l; i <= r; i ++){
        a[i] = ++ m;
    }
    
    for (int i = 1; i <= n; i ++)
        cout << a[i] << " \n"[i == n];
}

D. Test of Love

fag:DP

Solution:考慮如何從上一步轉移,跳過來或者游過來。

  • 注意\(m\)的範圍,可以直接列舉前\(m\)個格子(賽時沒看到範圍,用單調佇列最佳化DP做的)
  • 游過來的前提,上一格是水。
void solve(){
    cin >> n >> m >> k;
    string s;
    cin >> s;
    s = "$" + s;
    deque<int> qu;
    vector<int> f(n + 2, INF);

    f[0] = 0;
    qu.push_back(0);
    for (int i = 1; i <= n + 1; i ++){
        if (s[i] == 'C')
            continue;
        while (qu.size() && qu.front() + m < i){  // 儲存原木的座標
            qu.pop_front();
        }

        if (qu.size())
            f[i] = f[qu.front()];
        if (s[i - 1] == 'W')
            f[i] = min(f[i], f[i - 1] + 1);

        if (s[i] == 'L'){
            while (qu.size() && f[qu.back()] >= f[i])
                qu.pop_back();
            qu.push_back(i);
        }
    }

    if (f[n + 1] > k){
        cout << "NO\n";
    }
    else{
        cout << "YES\n";
    }
}

E. Novice's Mistake

fag:思維

Desription:給定一個\(n\),求出所有滿足條件的\(a, b\)組合。

  • \(1 <= a <= 1e4, 1 <= n <= 100\)
  • \(n * a - b\)等於將\(a\)個字串\(n\)然後刪去末尾\(b\)個字元之後代表的整數
  • \(n * a - b > 0\)

Solution:注意到字串的操作會影響答案的位數,但是數值計算\(n * a\)最多為\(1e6\)所以最大隻有\(6\)位。

  • 我們列舉\(a\),然後列舉答案的位數\(k\),對於每個\(k\)求出一個\(b\),判斷當前\(a, b\)是否滿足條件

Competing:賽場根本沒想到位數的關係

void solve(){
    string n;
    cin >> n;
    vector<pii> ans;

    for (int a = 1; a <= 10000; a ++){
        int len = to_string(stoi(n) * a).size();  // 當前位數
        // if (a == 1262)
        //     debug(len);
        for (int k = len; k; k --){
            int b = a * n.size() - k;
            if (!b) 
                continue;
            int t = 0;
            for (int i = 1, j = 0; i <= k; i ++){
                if (j == n.size())
                    j = 0;
                t = t * 10 + (n[j ++] - '0');
            }
            if (t == stoi(n) * a - b){
                ans.push_back({a, b});
            }
            // if (a == 1262 && b == 2519){
            //     debug(t, stoi(n) * a - b);
            // }
        }
    }
    cout << ans.size() << endl;
    for (auto [a, b] : ans){
        cout << a << " " << b << endl;
    }
}

F. Test of Love

fag:思維

Description:有\(n\)個數,給定一個\(x\),將\(n\)個數分為\(k\)個連續區間,每個區間滿足任意一個子集的乘積不等於\(x\)

1 <= n <= 1e5 2 <= x <= 1e5
1 <= a_i <= 2e5

Solution:從前往後模擬當前區間能夠得到那些因數(使用set去重),因為因數的個數很少,所以可做

Competing:沒考慮到使用\(set\)去重

void solve(){
    int x;
    cin >> n >> x;
    vector<int> a(n);
    set<int> v; // 記錄當前區間所有可能出現的x的約數
    for (int i = 0; i < n; i ++)
        cin >> a[i];

    int ans = 1;
    for (int i = 0; i < n; i ++){
        if (x % a[i])
            continue;
        set<int> tmp;
        for (auto j : v){
            tmp.ep(a[i] * j); // 記錄能夠構造出來的數
        }
        for (auto j : tmp){
            if (x % j)
                continue;
            v.ep(j);
        }
        if (v.find(x) != v.end()){
            ans ++;
            v.clear();
        }
        v.ep(a[i]);
    }
    cout << ans << endl;
}

相關文章