牛客小白月赛128

链接:https://ac.nowcoder.com/acm/contest/127265

A – 模糊匹配

算法:

模拟。

思路:

无。

关键代码:

void miyan()
{
    int n;
    string s, t;
    cin >> n >> s >> t;

    for (int i = 0; i < n; ++i)
    {
        if (s[i] == t[i])
            continue;

        if ((s[i] == '0' || s[i] == 'O') && (t[i] == '0' || t[i] == 'O'))
            continue;

        if ((s[i] == '1' || s[i] == 'l' || s[i] == 'I') && (t[i] == '1' || t[i] == 'l' || t[i] == 'I'))
            continue;

        cout << "NO" << endl;
        return;
    }

    cout << "YES" << endl;
}

B – 只留专一数

算法:

贪心,质因数分解。

思路:

手玩样例发现,只要存在任意一个数字,其质因数分解后质因子只有一个,那么就满足最后 \(a_1\) 是专一数。

特殊的,\(1\) 也满足要求。

关键代码:

vector<int> prime, minp, maxp;
void get_prime(int n)
{
    minp.resize(n + 1);
    maxp.resize(n + 1);
    for (int i = 2; i <= n; i++)
    {
        if (!minp[i])
        {
            minp[i] = maxp[i] = i;
            prime.push_back(i);
        }
        for (auto j : prime)
        {
            if (j > minp[i] || j > n / i)
                break;
            minp[i * j] = j;
            maxp[i * j] = maxp[i];
        }
    }
}

vector<array<int, 2>> factorize(int n)
{
    vector<array<int, 2>> ans;
    while (n > 1)
    {
        int now = minp[n], cnt = 0;
        while (n % now == 0)
        {
            n /= now;
            cnt++;
        }
        ans.push_back({now, cnt});
    }
    return ans;
}

void miyan()
{
    int n;
    cin >> n;
    vector<int> a(n);
    for (auto &x : a)
        cin >> x;

    for (int i = 0; i < n; ++i)
    {
        if (factorize(a[i]).size() <= 1)
        {
            cout << "YES" << endl;
            return;
        }
    }

    cout << "NO" << endl;
}

C – 左右左右左左右,左右左左右

算法:

模拟,贪心。

思路:

每次尝试添加 \(a_0\) 或者 \(a_1\),每次都取总贡献最小的即可。

具体实现看代码。

关键代码:

void miyan()
{
    int n, a0, a1;
    cin >> n >> a0 >> a1;

    string ans;
    ll val0 = 0, val1 = 0;
    for (int i = 1; i <= n; ++i)
    {
        if (abs((val1 + a0) - val0) >= abs(val1 - (val0 + a1)))
        {
            val0 += a1;
            ans += '0';
        }
        else
        {
            val1 += a0;
            ans += '1';
        }
    }

    cout << ans << endl;
}

D – 进退的艺术

算法:

二分,差分,前缀和,排序。

思路:

经典二分前缀和题目,不过多赘述。

关键代码:

void miyan()
{
    ll n, m;
    cin >> n >> m;
    vector<pair<ll, ll>> b(n);
    for (int i = 0; i < n; ++i)
    {
        cin >> b[i].first;
        b[i].second = i;
    }

    ranges::sort(b);

    vector<ll> c(n), s(n + 1, 0);
    for (int i = 0; i < n; ++i)
    {
        c[i] = b[i].first;
        s[i + 1] = s[i] + c[i];
    }

    vector<ll> ans(n);
    for (int i = 0; i < n; ++i)
    {
        ll cur = c[i];
        int R = upper_bound(c.begin(), c.end(), m - cur) - c.begin() - 1;

        ll cnt = R + 1;
        if (R >= i)
            cnt--;

        ll sco = cnt * cur;

        int L = R + 1;
        if (L < n)
        {
            ll sum = s[n] - s[L];
            if (i >= L)
                sum -= cur;
            sco -= sum;
        }

        ans[b[i].second] = sco;
    }

    for (int i = 0; i < n; ++i)
        cout << ans[i] << ' ';
    cout << endl;
}

E – 扫雷难度调节

算法:

构造。

思路:

将地图分为独立的 \(9\) 宫格(长度不足以到达 \(9\) 宫格的位置,取剩余的一部分),将地雷放到 \(9\) 宫格中心,以最大化数字格数量,此时数字格个数是地图最大数字格个数,不难想到计算公式 \(count = n * m – \lceil \frac{n}{3} \rceil * \lceil \frac{m}{3} \rceil\),如果 \(count\) 小于题目要求个数(设该个数为 \(k\)),那么题目无解;如果 \(count\) 题目大于 \(k\),则在任意位置多输出 \(count – k\) 个地雷格即可。

关键代码:

void miyan()
{
    int n, m, k;
    cin >> n >> m >> k;

    ll maxx = n * m - ((n + 2) / 3) * ((m + 2) / 3);
    if (maxx < k)
    {
        cout << -1 << endl;
        return;
    }

    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
            if ((i % 3 == 1 || (i % 3 == 0 && i + 1 == n)) && (j % 3 == 1 || (j % 3 == 0 && j + 1 == m)))
                cout << 1;
            else if (maxx > k)
            {
                --maxx;
                cout << 1;
            }
            else
                cout << 0;
        }

        cout << endl;
    }
}

F – 徽章计数

算法:

组合数学。

思路:

对于每个数值 \(x\),如果有 \(cnt[x]\) 个小朋友,那么值为 \(x\) 的小朋友会被分为 \(\frac{cnt[x]}{x}\) 组。

考虑无解的情况:

  • \(cnt[x]\) 无法被 \(x\) 整除;
  • \(\sum \frac{cnt[x]}{x} > m\)。

对于每个数值 \(x\),需要将 \(cnt[x]\) 个小朋友划分为 \(k = \frac{y}{x}\)​ 个大小为 \(x\) 的组,令 \(y = cnt[x]\)。

  • 先对这 \(y\) 个小朋友进行全排列,方案数为 \(y!\);
  • 将排列分为 \(k\) 组,每隔 \(x\) 个分为一组,共有 \(1\) 种方案;
  • 每组内的小朋友顺序无关(既每一组内的小朋友顺序任意),所以需要除去每组的排列数 \(x!\),共除以 \(x!^{k}\);
  • 组与组之间的顺序无关,需要再除以 \(k​!\);
  • 因此数值 \(x\) 的方案数为 \(\frac{y!}{x!^{k} * k!}\)。

对于 \(\sum \frac{cnt[x]}{x}\) 组小朋友,需要从 \(m\) 个徽章中选出 \(\sum \frac{cnt[x]}{x}\) 个分配给小朋友,那么小朋友之间徽章分配方案数为 \(P(m, \sum \frac{cnt[x]}{x}) \)种。

因此总的方案数为 \(\sum \frac{y!}{x!^{k} * k!} * P(m, \sum \frac{cnt[x]}{x})\)。

计算过程中对答案取模即可。

关键代码:

ll qmi(ll a, ll b, ll p)
{
    ll ans = 1 % p;
    while (b)
    {
        if (b & 1)
            ans = ans * a % p;
        b >>= 1;
        a = a * a % p;
    }

    return ans;
}

vector<ll> fact(N), inv(N);
void init()
{
    fact[0] = 1;
    for (int i = 1; i < N; i++)
        fact[i] = fact[i - 1] * i % MOD;
    inv[N - 1] = qmi(fact[N - 1], MOD - 2, MOD);
    for (int i = N - 2; i >= 0; i--)
        inv[i] = inv[i + 1] * (i + 1) % MOD;
}

void miyan()
{
    ll n, m;
    cin >> n >> m;
    vector<int> a(n);
    for (auto &x : a)
        cin >> x;

    map<int, ll> cnt;
    for (auto &x : a)
        ++cnt[x];

    ll sum = 0;
    ll tot = 0;
    for (auto &[x, y] : cnt)
    {
        if (y % x)
        {
            cout << 0 << endl;
            return;
        }

        tot += y / x;
        sum += y;
    }

    if (sum != n)
    {
        cout << 0 << endl;
        return;
    }

    ll ans = 1;
    while (tot--)
    {
        ans = (ans * m) % MOD;
        --m;
    }

    for (auto [x, y] : cnt)
    {
        ll k = y / x;
        ll Y = fact[y];
        ll X = qmi(inv[x], k, MOD);
        ll K = inv[k];
        ans = ans * Y % MOD * X % MOD * K % MOD;
    }

    cout << ans << endl;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇