//https://img2018.cnblogs.com/blog/1646268/201908/1646268-20190806114008215-138720377.jpg

QBXT-EIGHT

2023.11.10 第八场

T1

考虑怎么打暴力。

每次购买饮料的时候尽量给售货机多的零钱,然后就可以在零钱不够的时候,用大额的面值让售货机找零,如果此时没法找零,那么就不能继续买了。

然后可以发现,咱的零钱最多是 \(0\sim 1e6-1\) 的情况,因为再多了就可以当作纸币看待了,然后不难发现当手里的零钱和售货机里的零钱的总钱数大于等于 \(1e6\) 的时候,是一定可以保证能找零或者直接买饮料的。

设手里的零钱是 \(c\),售货机里的零钱是 \(d\),已知 \(c + d\ge 10^6\),我们大于 \(1e6\) 的部分就直接用大额的货币买了,所以一瓶脉动需要的零钱就是 \(R = r \bmod 10^6\),那么就是要证明 \(c \ge R\)\(d \ge 10^6 - R\) 之中一定有一个满足。

\(c + d\ge 10^6\) 可知 \(c \ge 10 ^ 6 - d\),设 \(c < R\),即其中第一个条件不满足,那么就可以得出 \(10^6 - d < R\),得到 \(10^6 - R < d\),也就是说当前是能找零的。

反之 \(10^6 - R > d\) 的时候 \(c > R\)

所以对于 \(c + d\le 10 ^ 6\) 的情况直接暴力,反之直接除就好了。

/*
 * @Author: Aisaka_Taiga
 * @Date: 2023-11-10 17:28:22
 * @LastEditTime: 2023-11-10 21:05:59
 * @LastEditors: Aisaka_Taiga
 * @FilePath: \Desktop\T1.cpp
 * The heart is higher than the sky, and life is thinner than paper.
 */
#include <bits/stdc++.h>

#define int long long
#define N 1000010

using namespace std;
 
inline int read()
{
    int x = 0, f = 1;
    char c = getchar(); 
    while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
    while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x * f; 
}

const int B = 1e6;
int b, c, r, d, ans;

signed main()
{
    b = read(), c = read();
    r = read(), d = read();
    if(c + d > 1e6)
    {
        ans = (b * B + c) / r;
        cout << ans << endl;
        return 0;
    }
    for( ; ; )
    {
        if(B * b + c < r) break;
        int c1 = r - r / B * B, c2 = r / B;
        while(c2 > b) c1 += B, c2 --;
        if(c2 < b)
        {
            c2 ++;
            c1 = B - c1;
            if(d >= c1)
            {
                b -= c2;
                d -= c1;
                c += c1;
                ans ++;
                continue;
            }
            c2 --;
            c1 = B - c1;
        }
        if(c1 <= c)
        {
            d += c1;
            b -= c2;
            c -= c1;
            ans ++;
            continue;
        }
        break;
    }
    cout << ans << endl;
    return 0;
}
/*
1999999 12312323
1 1233241
*/

T2

只会只有 YK 两个字符的情况。

发现这种情况一定要把所有的 k 都挪到 Y 左边,那么直接暴力找到第一个不是 Y 的地方,然后找到此后第一个是 K 的地方,然后一路 swap 过去,累加次数即可。


/*
 * @Author: Aisaka_Taiga
 * @Date: 2023-11-10 17:58:54
 * @LastEditTime: 2023-11-10 20:59:58
 * @LastEditors: Aisaka_Taiga
 * @FilePath: \Desktop\T2.cpp
 * The heart is higher than the sky, and life is thinner than paper.
 */
#include <bits/stdc++.h>

#define int long long
#define N 1001000

using namespace std;

inline int read() 
{
    int x = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
    while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x * f;
}

int ff, n, ans;
string s;

inline int work1(int l, int r)
{
    int t = l, kk = l, res = 0;
    while(s[t] == 'K' && t <= r) t ++;
    kk = t + 1;
    while(1)
    {
        while(s[kk] != 'K' && kk <= r) kk ++;
        if(kk > r) break;
        res += kk - t;
        for(int i = kk; i > t; i --)
            swap(s[i], s[i - 1]);
        // for(int i = 1; i <= n; i ++)
            // cout << s[i]; cout << endl;
        t ++;
        while(s[t] == 'K' && t <= r) t ++;
        if(t > r) break;
        kk ++;
    }
    return res;
}

inline void work2()//觀音菩薩保平安
{
    int l = 1, r = 0;
    while(1)
    {
        while(s[l] != 'K' && s[l] != 'Y' && l <= n) l ++;
        r = l;
        if(l > n) break;
        while((s[r] == 'K' || s[r] == 'Y') && r <= n) r ++;
        r --;
        // cout << " L : " << l << "   R  : " << r << endl;
        ans += work1(l, r);
        // cout << "ASN : " << ans << endl;
        l = r + 1;
    }
    return ;
}

signed main()
{
    cin >> n >> s;
    s = ' ' + s;
    for(int i = 1; i <= n; i ++)
        if(s[i] != 'Y' && s[i] != 'K'){ff = 1; break;}
    if(ff == 0) ans = work1(1, n);
    else work2();
    cout << ans << endl;
    return 0;
}

T3

考试写的分讨,但是错了。

很明显一个组分成一堆的 \(2,3\) 的小组,然后直接用这些 \(2,3\) 来放进圆桌里就好,明显的 \(3\) 的个数最少就是组内人数为奇数的组的个数,然后进行以下的分讨:

写伪代码吧

计算一个圆桌最多放多少个 $2$

如果 : 圆桌能放偶数个人

    优先放 $2$
    计算剩下的 $2$ 需要多少桌子。

如果 : 圆桌能放奇数个人

    如果 : 每组一个 $3$ 的话 $2$ 刚好
        输出 $3$ 的个数
    如果 : 每组一个 $3$ 的话不够
        不够的用 $2$
    如果 : 每组一个 $3$ 还有 $3$ 剩下
        计算剩下放 $3$ 后用的总数。
/*
 * @Author: Aisaka_Taiga
 * @Date: 2023-11-10 19:14:18
 * @LastEditTime: 2023-11-11 09:49:59
 * @LastEditors: Aisaka_Taiga
 * @FilePath: \Desktop\helloworld.cpp
 * The heart is higher than the sky, and life is thinner than paper.
 */
#include <bits/stdc++.h>

#define int long long
#define N 2000100

using namespace std;

inline int read()
{
    int x = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
    while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x * f;
}

int n, r, a[N], ans, c1, c2;
pair<int, int> s[N];

inline void work()
{
    int xx = a[1] + a[2];
        ans = ceil((double)(xx * 1.0 / r));
    cout << ans << endl;
    return ;
}

signed main()
{
    n = read(), r = read();
    for(int i = 1; i <= n; i ++) cin >> a[i];
    if(n <= 2) return work(), 0;
    for(int i = 1; i <= n; i ++)
    {
        ans += a[i] / r;
        a[i] %= r;
        if(a[i] == 1) a[i] += r, ans --;
        if(a[i] % 2 == 1) s[i] = {a[i] / 2 - 1, 1}, c2 ++;
        else s[i] = {a[i] / 2, 0};
        c1 += s[i].first;
    }
    int c3 = r / 2;
    if(r % 2 == 0)
    {
        ans += c1 / c3;
        int xx = c1 % c3;
        // if(xx == 0) return cout << ans << endl, 0;
        int yy = r - xx * 2;
        if(xx == 0 && c2 == 0) return cout << ans << endl, 0;
        ans ++;
        // cout << "C@ : " << c2 << endl;
        c2 -= yy / 3;
        if(c2 <= 0) return cout << ans << endl, 0;
        yy = r / 3;
        if(c2 % yy == 0) ans += c2 / yy;
        else ans += c2 / yy + 1;
    }
    else
    {
        c3 --;
        if(c1 == c3 * c2)
        {
            ans += c2;
            cout << ans << endl;
            return 0;
        }
        if(c1 > c3 * c2)
        {
            ans += c2;
            c1 -= c2 * c3;
            c3 ++;
            if(c1 % c3 == 0) ans += c1 / c3;
            else ans += c1 / c3 + 1;
        }
        else
        {
            ans += c1 / c3;
            c1 -= c1 / c3 * c3;
            c2 -= c1 / c3;
            int xx = r - c1 * 2;
            ans ++;
            c2 -= xx / 3;
            if(c2 <= 0) return cout << ans << endl, 0;
            xx = r / 3;
            if(c2 % xx == 0) ans += c2 / xx;
            else ans += c2 / xx + 1;
        }
    }
    cout << ans << endl;
    return 0;
}
/*
5 3
5 12 4 2 3
*/

T4

直接暴力枚举 \(1\sim n\) 每一个数选还是不选进集合,然后判断是不是好集合。


/*
 * @Author: Aisaka_Taiga
 * @Date: 2023-11-10 20:28:24
 * @LastEditTime: 2023-11-10 20:59:07
 * @LastEditors: Aisaka_Taiga
 * @FilePath: \Desktop\T4.cpp
 * The heart is higher than the sky, and life is thinner than paper.
 */
#include <bits/stdc++.h>

#define int long long
#define N 100100

using namespace std;

inline int read()
{
    int x = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
    while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x * f;
}

int n, b[N], ans;

inline void check()
{
    for(int i = 1; i <= n; i ++)
    {
        if(b[i] == 0) continue;
        for(int j = 1; j <= n; j ++)
        {
            if(b[j] == 0) continue;
            if((i + j) % 2 == 0 && !b[(i + j) / 2]) return ;
        }
    }
    // for(int i = 1; i <= n; i ++)
    //     if(b[i]) cout << i << " ";
    // cout << endl;
    ans ++;
    return ;
}

inline void dfs(int x)
{
    if(x == n + 1) return check(), void();
    dfs(x + 1);
    b[x] = 1;
    dfs(x + 1);
    b[x] = 0;
    return ;
}

signed main()
{
    n = read();
    dfs(1);
    cout << ans << endl;
    return 0;
}
posted @ 2023-11-13 08:40  北烛青澜  阅读(1)  评论(0编辑  收藏  举报