首页 > 其他分享 >IAEPC Preliminary Contest (Codeforces Round 999, Div. 1 + Div. 2)

IAEPC Preliminary Contest (Codeforces Round 999, Div. 1 + Div. 2)

时间:2025-01-21 18:26:11浏览次数:1  
标签:std Contest int 999 cin 老实人 ++ vector Div


A. Kevin and Arithmetic

题意:给你\(n\)个数,你一开始有一个\(x = 0\),每次你让\(x\)加上一个没用过的数,然后\(x\)会一直除二直到变成奇数。如果你加上一个数后能除2,分数加1,问分数最大多少。

奇数后面加奇数才能是偶数,但一开始\(x\)是零,那么需要一个偶数,否则只能浪费一个奇数。
所以如果有偶数就是奇数个数加1,否则是奇数个数减1.

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    int cnt[2]{};
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    	++ cnt[a[i] & 1];
    }

    if (cnt[0]) {
    	std::cout << 1 + cnt[1] << "\n";
    } else {
    	std::cout << std::max(0, cnt[1] - 1) << "\n";
    }
}

B. Kevin and Geometry

题意:\(n\)个数,你要选四个数组成等腰梯形。

对梯形作高发现两边是两个三角形,那么(上底-下底)/2是底边长,为了让梯形的两个腰边能够上上底,这个距离一定小于腰边。所以我们找两个相同的数作为腰边,然后找差值最小的两个数当上底和下底。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<i64> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::sort(a.begin(), a.end());

    int p = -1;
    for (int i = 0; i + 1 < n; ++ i) {
    	if (a[i] == a[i + 1]) {
    		p = i;
    		break;
    	}
    }

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

    for (int i = 0, j = 0; i + 1 < n; ++ i) {
        while (i == p || i == p + 1) {
            ++ i;
        }

        j = std::max(j, i);
        while (j == i || j == p || j == p + 1) {
            ++ j;
        }

        if (i < n && j < n && std::abs(a[i] - a[j]) < a[p] + a[p]) {
            std::cout << a[j] << " " << a[i] << " " << a[p] << " " << a[p] << "\n";
            return;
        }
    }

    std::cout << -1 << "\n";
}

C. Kevin and Puzzle

题意:\(n\)个人,每个人可能是老实人也可能是说谎者,老实人一定说真话。两个说谎者不能站一起。第\(i\)个说左边有\(a_i\)个骗子。问这些人可能的组合有多少。

\(f_{i_{0/1}}\)表示第\(i\)个是老实人/说谎者。那么如果\(i\)是老实人,看前面一个人怎么转移过来。如果前面那个人也是老实人,那么\(a_i = a_{i+1}\),因为\(i\)说真话,\(i-1\)也是老实人,那么\(i-1\)左边的老实人应该等于\(a_i\)说的,不然两个人不可能同时是老实人。如果\(i-1\)是说谎者,那么因为两个说谎者不能站一起,第\(i-2\)个人一定是老实人,因为\(i-1\)是说谎者,那么到\(i-2\)这里还有\(a_i - 1\)个说谎者,看能不能对上就行。
如果\(i\)说谎,那么\(i-1\)一定使老实人,\(f_{i_0} = f_{i-1_1}\)。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n + 1);
    for (int i = 1; i <= n; ++ i) {
    	std::cin >> a[i];
    }

    if (n == 1) {
        std::cout << (1 + (a[1] == 0)) << "\n";
        return;
    }

    std::vector f(n + 1, std::array<Z, 2>{});
    f[1][0] = a[1] == 0;
    f[1][1] = 1;
    for (int i = 2; i <= n; ++ i) {
        if (a[i] == a[i - 1]) {
            f[i][0] += f[i - 1][0];
        }

        if (i >= 2 && a[i] - 1 == a[i - 2]) {
            f[i][0] += f[i - 1][1];
        }

        f[i][1] = f[i - 1][0];
    }

    std::cout << f[n][0] + f[n][1] << "\n";
 }

D. Kevin and Numbers

题意:两个数字\(A\)和\(B\),每次可以从\(A\)里选两个数,满足他们的差绝对值小于等于1,然后把这两个数删掉,然后把他们的和加入\(A\),问\(A\)能不能变成\(B\)。

考虑反着来,从\(B\)到\(A\),那么发现如果\(B\)的最大值大于\(A\)的最大值,那么这个最大值必须拆开,发现拆开的方式是唯一的。于是模拟就行。
注意最多操作\(n-m\)次,一直操作可能超时。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::priority_queue<int> a, b;
    for (int i = 0; i < n; ++ i) {
    	int x;
    	std::cin >> x;
        a.push(x);
    }

    for (int i = 0; i < m; ++ i) {
    	int x;
    	std::cin >> x;
        b.push(x);
    }

    i64 sum = n - m;

    while (sum >= 0 && a.size() && b.size()) {
    	if (a.top() == b.top()) {
            a.pop();
            b.pop();
        } else if (sum > 0) {
            int u = b.top(); b.pop();
            b.push(u / 2);
            b.push(u - u / 2);
            -- sum;
        } else {
            break;
        }
    }

    if (a.empty() && b.empty()) {
    	std::cout << "YES\n";
    } else {
    	std::cout << "NO\n";
    }
}

E. Kevin and And

题意:\(n\)个数,你有\(m\)个数让他们操作,每次可以选一个\(i\)和\(j\),然后\(a_i \&= b_j\),求最多\(k\)次操作让数组和最小。

发现\(m\)很小,枚举所有操作可以与的数。 然后计算\(f_{ij}\)表示第\(a_i\)操作\(j\)次最多减小多少,然后差分一下,记\(d_{i,j}\)为\(a_i\)操作\(j\)次比操作\(j-1\)次可以多减少的值。就可以用优先级队列记录一次操作可以减少的最大值。

点击查看代码
void solve() {
    int n, m, k;
    std::cin >> n >> m >> k;
    std::vector<i64> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::vector<i64> b(m);
    for (int i = 0; i < m; ++ i) {
    	std::cin >> b[i];
    }

    std::vector<std::vector<i64> > op(m + 1);
    for (int i = 0; i < 1 << m; ++ i) {
        i64 x = (1ll << 30) - 1;
        int cnt = 0;
        for (int j = 0; j < m; ++ j) {
            if (i >> j & 1) {
                x &= b[j];
                ++ cnt;
            }
        }

        op[cnt].push_back(x);
    }

    std::vector d(n, std::vector<i64>(m + 1));
    for (int i = 0; i < n; ++ i) {
        for (int j = 1; j <= m; ++ j) {
            for (auto & x : op[j]) {
                d[i][j] = std::max(d[i][j], a[i] - (a[i] & x));
            }

            d[i][j] = std::max(d[i][j], d[i][j - 1]);
        }

        for (int j = m; j >= 1; -- j) {
            d[i][j] = d[i][j] - d[i][j - 1];
        }
    }

    std::priority_queue<std::array<i64, 3> > heap;
    for (int i = 0; i < n; ++ i) {
        heap.push({d[i][1], 1, i});
    }

    i64 ans = std::accumulate(a.begin(), a.end(), 0ll);
    while (k -- ) {
        auto [x, cnt, id] = heap.top(); heap.pop();
        ans -= x;
        if (cnt + 1 <= m) {
            heap.push({d[id][cnt + 1], cnt + 1, id});
        }
    }

    std::cout << ans << "\n";
}

标签:std,Contest,int,999,cin,老实人,++,vector,Div
From: https://www.cnblogs.com/maburb/p/18684022

相关文章

  • 使用 div 自定义 input 和 textarea
    1.为什么要自定义呢?原生的 input和textarea在某些特定场景下存在功能或兼容性限制,因此使用div元素自定义实现,突破原生输入框在样式、功能、兼容性上的限制。1、解决火狐浏览器换行问题某些版本的火狐浏览器中,原生 textarea 存在回车不换行而显示为空格的问题。这种......
  • Codeforces Round 999 比赛记录
    前情提要这个菜鸡CF上了\(\color{darkcyan}Specialist\),心情大好,正好赶上放假,决定打一场CF。赛时记录A上来脑子抽了,吃了一发罚时。发现写错了一种情况,改过来就过了。感觉并不是一个好的开始。B竟成为本人唯一一遍过的题,虽然写的时候有点慌。CDP。一开始认为空间不够,但发......
  • CF div1+2 999 (A~E)
    赛时三题,\(D\)就差一个显然的剪枝就能过了,qwq...A显然第一步能选偶数就选偶数,之后只能选奇数。细节见代码。codeB对于选取的任意四条边,设腰为\(x\),短边为\(a\),长边为\(b\),则能形成等腰梯形的充要条件为:\(x\)出现次数\(>=2\),且\(a+2*x>b\)。两个腰选最大,并且\(a,b\)尽可能接近......
  • 写一个方法来获取div到浏览器窗口的高度
    在前端开发中,你可以使用JavaScript的getBoundingClientRect()方法来获取一个元素(比如div)相对于浏览器窗口的位置和大小。这个方法返回一个DOMRect对象,其中包含了top、right、bottom和left等属性,分别表示元素各边到视口(viewport)的距离。为了获取一个div元素到浏览器窗口顶部的高度......
  • 2024 (ICPC) Jiangxi Provincial Contest I 题 Neuvillette Circling题解
    简单思路一个圆套中了几个点,如果不断缩小这个圆,那么最终的结果有两种有两个点卡住了这个圆,且这两点一定是直径有三个或者三个以上的点卡住了这个圆,圆心在这三个点围成的三角形的外接圆圆心。因此我们枚举两点作为直径,或者枚举三个点作为圆的内接三角形,求这个三角形的外接圆......
  • 2024 (ICPC) Jiangxi Provincial Contest L 题 Campus 题解
    简单思路首先对于所有的出口求一遍最短路,由于出口只会打开并关闭一次,所以大门的开启状态是相当有限的(最多大概30种),我们对于每一种状态直接暴力求答案最后输出即可。复杂度大概\(O(knlogn)\)参考代码#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;type......
  • VP AtCoder Beginner Contest 380
    A-123233模拟即可。点击查看代码voidsolve(){intcnt[10]{};intn;std::cin>>n;while(n){ ++cnt[n%10]; n/=10;}for(inti=1;i<=3;++i){ if(cnt[i]!=i){ std::cout<<"No\n&qu......
  • Codeforces Round 998 (Div. 3) 部分题解
    写题解的时候这场在评测,就不放代码了。E.GraphComposition题意给两个无向简单图,对图\(1\)添加若干条边或删除若干条边,使得两图的连通性一致,最少需要变更多少条边。题解求出图\(2\)的连通性,考虑图\(1\)的所有边,若违背了图\(2\)联通性的要删除(图\(2\)不联通但图\(......
  • Codeforces Round 998 (Div. 3)
    题目链接:CodeforcesRound998(Div.3)总结:复建,Cwa两发,E读假题了。A.Fibonaccinesstag:签到Solution:简单模拟一下即可。voidsolve(){inta[5];for(inti=0;i<5;i++){if(i==2){continue;}cin>>a[i];......
  • CF div3 998(F,G)
    F\(dp\)+组合数学需要注意,数组中\(>1\)的数字个数不会超过\(log_{2}k\)个。先暂时不考虑\(1\)的摆放,只考虑所有\(>1\)的数:设\(f_{l,i}:\)长度为\(l\),乘积为\(i\),且所有元素均\(>1\)的数组个数考虑数组的最后一个元素\(d\),必有\(d|i\)成立,因为每个元素一定是\(i\)的因子。则......