2025.7.17(补)

刷题日记

傻逼


Codeforces Round 1037 (Div. 3) D. This Is the Last Time
https://codeforces.com/contest/2126/problem/D
给定n个“赌场”,每个赌场有三个属性:l,r,real
如果当前钱币数在l和r之间,则可通过这个赌场将当前钱币数变为real
可以不必选择所有的赌场,顺序也可以任选,求可能获得的最大钱币数
如果没有限制的话,这道题就不能用贪心的思路了,需要考虑搜索或DP
但是这道题题目限制real一定在l和r之间,所以只需要结构体排序一下即可
我他妈真是个傻逼

点击查看代码

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

    typedef struct node {
        int l, r, real;
    } node;

    std::vector<node> a(n + 1);
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i].l >> a[i].r >> a[i].real;
    }
    
    std::sort(a.begin() + 1, a.end(), [&] (node a, node b) {
        if (a.real != b.real) return a.real < b.real;
        if (a.l != b.l) return a.l < b.l;
        return a.r > b.r;
    });

    for (int i = 1; i <= n; i++) {
        if (a[i].l <= k && k <= a[i].r) {
            k = std::max(a[i].real, k);
        }
    }
    std::cout << k << '\n';
}

再给个广搜写法的代码,会超时,但是如果这道题real无限制,那么可能就是这种思路

点击查看代码

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

    typedef struct node {
        int l, r, real;
    } node;

    std::vector<node> a(n + 1);
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i].l >> a[i].r >> a[i].real;
    }

    std::queue<int> q;
    std::vector<int> vis(n + 1, 0);

    q.push(k);
    int ans = k;
    while (q.size()) {
        auto now = q.front();
        ans = std::max(ans, now);
        q.pop();

        for (int i = 1; i <= n; i++) {
            if (!vis[i] && a[i].l <= now && now <= a[i].r) {
                q.push(a[i].real);
                vis[i] = 1;
            }
        }
    }
    std::cout << ans << '\n';
}



Codeforces Round 1037 (Div. 3) E. G-C-D, Unlucky!
给定两个数组p和s,分别为某数组的前缀GCD数组和后缀GCD数组,请判断是否合法
这道题的思路特别简单,首先我们知道
前缀GCD数组p[i] = std::__gcd(p[i - 1], a[i]);
后缀GCD数组s[i] = std::__gcd(s[i + 1], a[i]);
那么我们可以知道,a[i] % p[i] == 0 && a[i] % s[i] == 0 一定成立
因此我们可以令a[i] = LCM(p[i], s[i]),也是满足条件的
我们构造出了数组a之后,再去求数组a的前后缀GCD数组,和题中给的数组比较
如果一模一样就输出YES,反之NO,代码如下

点击查看代码

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

    std::vector<i64> pre(n + 1), suf(n + 1);
    std::vector<i64> a(n + 1), p(n + 1), s(n + 1);

    for (int i = 1; i <= n; i++) {
        std::cin >> pre[i];
    }
    for (int i = 1; i <= n; i++) {
        std::cin >> suf[i];
    }   

    for (int i = 1; i <= n; i++) {
        a[i] = pre[i] * suf[i] / std::__gcd(pre[i], suf[i]);
    }

    p[1] = a[1], s[n] = a[n];
    for (int i = 2; i <= n; i++) {
        p[i] = std::__gcd(p[i - 1], a[i]);
    }
    for (int i = n - 1; i >= 1; i--) {
        s[i] = std::__gcd(s[i + 1], a[i]);
    }

    for (int i = 1; i <= n; i++) {
        if (p[i] != pre[i] || s[i] != suf[i]) {
            std::cout << "NO\n";
            return;
        }
    }
    std::cout << "YES\n";
}



Codeforces Round 1011 (Div. 2) C. Serval and The Formula
https://codeforces.com/problemset/problem/2085/C
给定两个正整数x,y,请找到一个k ∈ [0, 1e18],使得 (x + k) + (y + k) == (x + k) ^ (y + k)
我们设a = x + k, b = y + k,为了使得a + b == a ^ b,需要满足什么呢?
我们用二进制来表示,对于10101 和 01010,我们可以发现他们满足这个等式
也就是说,对于a和b两个数,如果他们任何一个二进制位都没有同时为1,那么就满足a + b == a ^ b!
换句话说,a + b == a ^ b 等价于 a & b == 0!
又因为2的幂的二进制表示总是1000000000这样的,并且2的幂,与任何小于它的正整数都没有公共位
所以我们的目的是,让x或者y,其中一个+k之后变成2的幂次,代码如下

点击查看代码

void solve () {
/*
    对于 a + b == a ^ b
    说明 对于a和b上任何一个二进制位,都没有同时为1的情况
    也就是说 a & b == 0

    因为2的幂的二进制表示总是1000000000这样的
    并且2的幂,与任何小于它的正整数都没有公共位
    所以我们的目的是,让x或者y,其中一个+k之后变成2的幂次
*/
    i64 x, y;
    std::cin >> x >> y;

    if (x == y) {
        std::cout << "-1\n";
        return;
    }

    std::cout << (1LL << 48) - std::max(x, y) << '\n';
}


posted @ 2025-07-18 15:54  _彩云归  阅读(63)  评论(0)    收藏  举报