Codeforces Round 1043 (Div. 3) (A ~ C2)

A. Homework

模拟

题意:

给定一个字符串,然后按照要求进行首尾添加,\(V\)放前面\(D\)放后面

思路:

按题意模拟即可

代码:

void solve()
{
    int n;
    cin >> n;

    string a;
    cin >> a;

    int m;
    cin >> m;

    string b,c;
    cin >> b >> c;

    int idx = 0;
    for(auto x : c) 
    {
        if(x == 'D') a += b[idx ++];
        else a = b[idx ++] + a;
    }

    cout << a << '\n';
}

B. The Secret Number

数学

题意:

给定一个\(n\)并规定\(n = x + y\),y是在x右面添加若干个0得到的,升序输出符合规定的所有\(x\)

思路:

不难发现\(y = 10 * c * x\),那么\(n = (10 * c + 1) * x\),所以只需枚举\(c\)也就是在x右面添加多少个\(0\),如果这个系数能整除\(n\),此时这个\(x\)就是答案之一,最后排序输出即可

代码:

void solve()
{
    int n;
    cin >> n;

    vector<int> res;
    for(int i = 10; ; i *= 10)
    {
        int t = i + 1;

        if(t > n) break;

        if(n % t == 0) res.push_back(n / t);
    }

    sort(res.begin(),res.end());
    cout << res.size() << '\n';
    for(auto x : res) cout << x << ' ';
    if(res.size() != 0) cout << '\n';
}

C1. The Cunning Seller (easy version)

贪心

题意:

你去买西瓜,每次交易可用\(3^{x + 1} + x * 3^{x - 1}\)金币买\(3^x\)个西瓜\((x >= 0)\),在保证最少交易次数前提下求购买n个西瓜所需最少金币

思路:

可以先预处理一下买\(3^i\)个西瓜所需金币数量,然后将\(n\)转换成\(3\)进制,从高位到低位计算一下即可

代码:

void solve()
{
    int n;
    cin >> n;

    vector<int> c(21),pre(21);

    pre[0] = 1;
    for(int i = 1; i <= 20; i ++) pre[i] = pre[i - 1] * 3;
    
    c[0] = 3;
    for(int i = 1; i <= 20; i ++) c[i] = pre[i + 1] + i * pre[i - 1];

    int res = 0;
    for(int i = 20; i >= 0; i --)
    {
        if(n >= pre[i]) 
        {
            int num = n / pre[i];
            n %= pre[i];

            res += num * c[i];
        }
    }

    cout << res << '\n';
}

C2. The Cunning Seller (hard version)

贪心
代码写的有点拉了

题意:

与上一题唯一区别是本题要求在保证交易次数不超过\(k\)次购买\(n\)个西瓜所需最少金币数,如果无法在不超过\(k\)次的限制下买\(n\)个西瓜,那么就输出\(-1\)

思路:

首先可以利用上一题计算出购买\(n\)个瓜最小交易次数,如果最小交易次数都大于\(k\)就是无解,那么如何更优的购买呢?

\[\frac{3^{x + 1} + x * 3^{x - 1}} {3^x} = x + \frac{x}{3} \]

所以不难发现随着\(x\)增大,西瓜单价是递增的,然后还有一个性质就是一个\(i\)等价于\(3\)\(i - 1\)交易次数较原来增加了\(2\),所以剩下在满足交易次数小于等于k的条件下从高到低要尽可能的将\(n\)所对应的\(3\)进制数位转换到低位,最后计算结果即可

代码:

void solve()
{
    int n,k;
    cin >> n >> k;

    int res = 0;
    vector<int> a(22);
    for(int i = 20; i >= 0; i --)
    {
        if(n >= pre[i]) 
        {
            int num = n / pre[i];
            n %= pre[i];

            a[i] = num;
            res += num;
        }
    }

    if(res > k)
    {
        cout << -1 << '\n';
        return;
    }
    
    for(int i = 20; i > 0; i --)
    {
        if(!a[i]) continue;

        if(res + 2 > k) break;  

        int cnt = (k - res) / 2;

        if(cnt <= 0) break;

        if(cnt >= a[i]) 
        {
            a[i - 1] += a[i] * 3;
            res += a[i] * 2;
            a[i] = 0;
        }
        else 
        {
            a[i - 1] += cnt * 3;
            res += cnt * 2;
            a[i] -= cnt;
        }
    }

    int cost = 0;
    for(int i = 0; i <= 20; i ++)
        cost += c[i] * a[i];

    cout << cost << '\n';
}
posted @ 2025-08-25 20:38  Gabriel_7  阅读(14)  评论(0)    收藏  举报