10 - 2 ~ 10 - 3 模擬賽報告

Darkworldmystery發表於2024-10-02

啟動新賽季!

10.2

題目一覽:

題目名稱 躲避技能 奶茶兌換券 幫助 神奇的變換
題目型別 傳統 傳統 傳統 傳統
檔名 skill tea help change
時空限制 \(2s256M\) \(1s256M\) \(2s256M\) \(5s256M\)
測試點數量 \(25\) \(10\) \(20\) \(25\)

請觀看 VCR,並回答作者表達的情感。


  • \(\texttt{『S』}\) 今天我們充分發揚 PTY 告訴我們的策略!

那我們直接把暴力分拿滿!

T1

題面:有一棵樹,一些節點上有若干個箱子,要把所有箱子推到若干節點的坑中(坑中可能可以填一個或者多個),經過每一條邊都有相應代價,求完成任務最小的代價。

思路:

直接建樹爆搜,然後全排列,複雜度 \(O(m !)\)

// Darkworldmystery 2023 ~ 2024
// #pragma GCC optimize("Ofast")
#include<bits/stdc++.h>

using namespace std;
using LL = long long;

const LL kMaxN = 1e5 + 5;

struct Edge
{
    LL to, w;
} ;

LL n, m, s[kMaxN], imp[kMaxN], dis[15][kMaxN], id[kMaxN], ret = 1e18;
vector<Edge> nbr[kMaxN];

LL refc(string x)
{
    int ret = 0;
    for(int i = x.size() - 1; i >= 0; i--)
        ret = ret * 10 + (x[i] - '0');
    return ret;
}

void dfs(LL x, LL father, LL root = 1)
{
    for(LL i = 0; i < nbr[x].size(); i++)
    {
        LL y = nbr[x][i].to, w = nbr[x][i].w;
        if(y == father)
            continue;
        dis[root][y] = dis[root][x] + w;
        dfs(y, x, root);
    }
    return ;
}


int main()
{
    freopen("skill.in", "r", stdin);
    freopen("skill.out", "w", stdout);
    ios :: sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n >> m;
    for(LL i = 1; i <= m; i++)
        cin >> s[i], id[i] = i;
    for(LL i = 1; i <= m; i++)
        cin >> imp[i];
    for(LL i = 1, x, y, w; i < n; i++)
    {
        string ww;
        cin >> x >> y;
        cin >> ww;
        w = refc(ww);
        // cerr << w << "\n";
        nbr[x].push_back({y, w});
        nbr[y].push_back({x, w});
    }
    dfs(1, 0);
    for(LL i = 1; i <= m; i++)
        dfs(s[i], 0, s[i]);
    do 
    {
        LL B = 0;
        for(int i = 1; i <= m; i++)
            B += dis[s[i]][imp[i]];
        ret = min(ret, B);
    } while(next_permutation(s + 1, s + 1 + m));
    cout << ret << "\n";
    return 0;
}

如願以償地拿到了暴力 \(\color{red} 20 pt\)

T2

題面:玥玥有無限張價值 \(m\) 的奶茶代金券,每次玥玥會使用代金券購買兩杯奶茶。只有當代金券的總價值大於等於奶茶的總價值才可以購買,但是奶茶店是不找零的。

假設每張代金券價值 \(10\) 元,然後買了一杯 \(11\) 元和一杯 \(4\) 元的奶茶。則需要兩張代金券才能購買,但是兩張代金券價值 \(20\),奶茶總價值 \(15\),即我們可以認為玥玥這樣做浪費了 \(5\) 元。

現在已知玥玥總共購買了 \(n\) 種價值的奶茶,第 \(i\) 種奶茶購買的數量為 \(a_i\),價格為 \(b_i\)。請問玥玥最少浪費多少錢?

思路:直接列舉所有搭配,然後和這個搭配浪費的錢用 vector 存起來,然後貪浪費的錢少的,然後枚到沒了為止。

也是非常好寫。

// Darkworldmystery 2023 ~ 2024
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>

using namespace std;
using LL = long long;

const LL kMaxN = 1e5 + 5;

struct Milktea
{
    LL x, price;
    friend bool operator < (const Milktea &x, const Milktea &y)
    {
        return x.price < y.price;
    }
} a[kMaxN];
struct E
{
    LL a, b, D;
    friend bool operator < (const E &x, const E &y)
    {
        return x.D < y.D;
    }
} ;

vector<E> vt;
LL n, m, ret;


int main()
{
    freopen("tea.in", "r", stdin);
    freopen("tea.out", "w", stdout);
    ios :: sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n >> m;
    for(LL i = 1; i <= n; i++)
        cin >> a[i].x >> a[i].price;
    sort(a + 1, a + 1 + n);
    if(n <= 1000)
    {
        for(LL i = 1; i <= n; i++)
            for(LL j = i; j <= n; j++)
                vt.push_back({i, j, (m - (a[i].price + a[j].price) % m == m ? 0 : m - (a[i].price + a[j].price) % m)});
        sort(vt.begin(), vt.end());
        for(auto i : vt)   
        {
            LL x = i.a, y = i.b, w = i.D, T = min(a[x].x, a[y].x);
            if(x == y)
                T /= 2;
            if(a[x].x <= 0 || a[y].x <= 0)
                continue;
            a[x].x -= T, a[y].x -= T;
            ret += w * T;
        }
        cout << ret << "\n";
        return 0;
    }
    cout << "1145141919810" << "\n";
    return 0;
}

順利的拿到了 \(\color{orange} 30 pt\)

\(30 \%\) 的性質聽了感覺非常無語,不過因為資料出鍋沒有這個性質的資料

T3

題面:\(n\) 個人,第 \(i\) 個人的 EQ \(x_i\) 和 IQ \(y_i\),每個人的 EQ 都不一樣。

\(i\) 個人可以分享自己的 IQ 給 EQ 在 \([c_i, d_i]\) 的人,也願意接受 EQ 在 \([a_i, b_i]\) 的人,不屬於自己的 IQ 不可以再分享給別人

在他們儘可能分享自己的腦子 IQ 的情況下,每個人的 IQ。

思路:好啊這波更簡單,直接按題意模擬。

// Darkworldmystery 2023 ~ 2024
// #pragma GCC optimize("Ofast")
#include<bits/stdc++.h>

using namespace std;
using LL = long long;

const LL kMaxN = 1e5 + 5;

struct Point
{
    LL num, score, ans = 1, mine;
    pair<LL, LL> allow, help;
} a[kMaxN];

LL n;

bool check(Point x, Point y)
{
    return x.score >= y.allow.first && 
           x.score <= y.allow.second &&
           y.score >= x.help.first &&
           y.score <= x.help.second;
}

int main()
{
    freopen("help.in", "r", stdin);
    freopen("help.out", "w", stdout);
    ios :: sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n;
    for(LL i = 1; i <= n; i++)
        cin >> a[i].num, a[i].ans = a[i].num;
    for(LL i = 1; i <= n; i++)
        cin >> a[i].score;
    for(LL i = 1; i <= n; i++)
        cin >> a[i].allow.first >> a[i].allow.second >> a[i].help.first >> a[i].help.second;
    if(n <= 1000)
    {
        for(LL i = 1; i <= n; i++)
            for(LL j = i + 1; j <= n; j++)
            {
                if(check(a[i], a[j]))
                    a[j].ans += a[i].num;
                if(check(a[j], a[i]))
                    a[i].ans += a[j].num;
            }
        for(LL i = 1; i <= n; i++)
            cout << a[i].ans << " ";
    }
    return 0;
}

成功拿到了 \(\color{orange} 30 pt\)

T4

題面:有一天,玥玥在電視上,看到了一種神奇的數字變換。

這種變換首先需要我們拿到一個正整數,然後對它分別進行以下分解:

  1. 分解它的質因數,數一數其質因數的指數,如果有一個質因數的指數 \(\ge 2\),寫下 \(0\);否則,若有奇數個質因數,寫下 \(−1\),否則寫下 \(1\)
  2. 分解其所有正約數,寫下其約數個數以及約數總和。

顯然,對於每一個數 \(x\),經過變換後將得到 \(3\) 個整數。

玥玥試了試,發現他算出了正確的答案,他太開心了!

然而,很不幸,這一切被玥玥的老師看見了。老師總算是找到了給玥玥出題的機會,於是在第二天,老師給玥玥留了一道《好》題。

老師給玥玥了 \(n\) 個正整數,排成一排。老師讓玥玥仔細看看這個序列(名字叫 \(a\)),然後告訴了玥玥他會問 \(q\) 個問題。每一個問題中,老師給出兩個數 \(l, r\),讓玥玥算出數字 \(x\) 的答案,其中 \(x = \displaystyle\prod_{i = l} ^ {r} a_i\)

玥玥:老師,這個數(指 \(x\))太大了怎麼辦?

老師:沒關係,你只需要告訴我答案對 \(10 ^ 9 + 7\) 取模的結果就行了(完全理解成了答案太大)。實在不行的話,可以請別人幫忙哦。

這下可把玥玥難住了。她請班上 OI 最強的你來幫他解決這個問題,畢竟,這可能會給她加不少德育分啊!

老師比較善良,所以每一次回答問題時,只需要回答答案中的第 \(type\) 問就可以。注意,這裡的輸出 \(x\) 的答案指的是輸出 \(y\) 經過上述變換得到的 \(3\) 個整數中的第 \(type\) 個。

由於老師的問題是一個一個問的,所以本題強制線上。

思路:依然暴力(不過有一個 \(type = 3\) 的沒時間寫了)

// Darkworldmystery 2023 ~ 2024
// #pragma GCC optimize("Ofast")
#include<bits/stdc++.h>

using namespace std;
using LL = long long;

const int kMaxN = 1e5 + 5, kMod = 1e9 + 7;

int n, q, a[kMaxN], opt, T;

int main()
{
    freopen("change.in", "r", stdin);
    freopen("change.out", "w", stdout);
    ios :: sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n >> q >> opt;
    for(int i = 1; i <= n; i++)
        cin >> a[i];
    for(int l, r; q; q--)
    {
        cin >> l >> r;
        l ^= T, r ^= T;
        LL x = 1;
        for(int i = l; i <= r; i++)
            x *= a[i];
        if(opt == 1)
        {
            LL sum = 0, cnt = 0;
            bool f = 0;   
            for(int i = 2; i <= x; i++)
            {
                if(x % i == 0)
                {
                    sum++;
                    x /= i;
                }
                while(x % i == 0)
                    f = 1, x /= i;
            }
            if(f == 1)
                cout << "0\n", T = 0;
            else if(sum & 1 == 1)
                cout << kMod - 1 << "\n", T = kMod - 1;
            else
                cout << "1\n", T = 1;
        }
        else if(opt == 2)
        {
            LL ret = 0;
            for(int i = 1; i * i <= x; i++)
            {
                if(x % i == 0)
                {
                    LL j = n / i;
                    (ret += 2) %= kMod;
                }
            }
            cout << (ret + kMod) % kMod << "\n";
            T = (ret + kMod) % kMod;
        }
        // else if(opt == 3)
        // {
        //     LL ret = 0;
        //     for(int i = 1; i <= sqrt(x); i++)
        //     {
        //         if(x % i == 0)
        //         {
        //             LL j = n / i;
        //             (ret += i + j) %= kMod;
        //         }
        //     }
        //     cout << (ret + kMod) % kMod << "\n";
        //     T = (ret + kMod) % kMod;
        // }
    }
    return 0;
}

預估的是 \(\color{red} 24 pt\),但是折了半,只有 \(\color{red} 12 pt\),不過賽後 mmt 的一句話,讓我感覺很離譜了。

你怎麼沒有判完全平方數啊?