VP Codeforces Round 904 (Div. 2)


A. Simple Design

题意:找大于等于x的第一个数位和是k的倍数的数。

k很小,则答案不会大于x很多。暴力枚举即可。

点击查看代码
void solve() {
    int n, k;
    std::cin >> n >> k;
    for (int i = n; ; ++ i) {
    	int x = i, s = 0;
    	while (x) {
    		s += x % 10;
    		x /= 10;
    	}

    	if (s % k == 0) {
    		std::cout << i << "\n";
    		return;
    	}
    }
}

B. Haunted House

题意:给你一个01串,每次你可以移动相邻的两个数,求对于每个i,让1i位都是0最小操作数。

我们从低到高模拟,我们每次都要移动一段1,那么我们记录1的数量,当遇到一个零的时候就代表前面这些1都需要移动一次使得cnt1位是0。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::string s;
    std::cin >> s;
    std::vector<i64> ans(n, -1);
    i64 sum = 0, cnt = 0;
    for (int i = n - 1; i >= 0; -- i) {
    	if (s[i] == '1') {
    		++ cnt;
    	} else {
    		sum += cnt;
    		ans[i + cnt] = sum;
    	}
    }

    std::reverse(ans.begin(), ans.end());

    for (int i = 0; i < n; ++ i) {
    	std::cout << ans[i] << " \n"[i == n - 1];
    }
}

C. Medium Design

题意:选一些线段,每个线段使得一个区间的数加一。使得最大值减最小值最大。

一个错误的贪心是先求一个最大值的位置,然后不包含这个位置的线段都不选,然后求出来最小值。
这个的hackm=3,(1,2),(1,2),(2,3),(2,3),(3,3)。发现不选所有的(1,2)答案是3,但按照这个贪心不能求出正确答案。
正确思路是记录每个点包含它的线段,以及包含它的线段完整包含了几次整个区间。可以先按线段左端点排序,然后枚举点一个一个线段加,在用个优先队列存右端点,每次删去不合法的对头。
注意需要离散化。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<std::pair<int, int>> a(n);
    std::vector<int> b;
    for (int i = 0; i < n; ++ i) {	
    	int l, r;
    	std::cin >> l >> r;
    	a[i] = {l, r};
    	b.push_back(l);
    	b.push_back(r);
    }

    b.push_back(1);
    b.push_back(m);

    std::sort(b.begin(), b.end());
    b.erase(std::unique(b.begin(), b.end()), b.end());

    auto get = [&](int x) -> int {
    	return std::lower_bound(b.begin(), b.end(), x) - b.begin() + 1;
    };

    int k = b.size();
    std::vector<int> d(k + 2);
    for (auto & [l, r] : a) {
    	l = get(l), r = get(r);
    }

    std::sort(a.begin(), a.end());
    using PII = std::pair<int, int>;
    std::priority_queue<PII, std::vector<PII>, std::greater<PII>> heap;
    int pre = 0, suf = 0;
    int ans = 0;
    for (int i = 1, j = 0; i <= k; ++ i) {
    	while (heap.size() && heap.top().first < i) {
    		if (heap.top().second == 1) {
    			-- pre;
    		}
    		heap.pop();
    	}

    	while (j < n && a[j].first == i) {
    		if (a[j].first == 1) {
    			++ pre;
    		}

    		if (a[j].second == k) {
    			++ suf;
    		}
    		heap.push({a[j].second, a[j].first});
    		++ j;
    	}

    	ans = std::max(ans, (int)heap.size() - std::min(pre, suf));
    }

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

D. Counting Rhyme

题意:求n个数里有多少对数没有共同的因子出现在这些数里面。

ak|ai,ak|ajak|(ai,aj)
那么我们枚举最大公约数,记gi为有多少对数的最大公约数是i的数量,cntii的倍数的数量。
那么有gi=cnti(cnti1)2i|jgj。对于一个数x,如果它出现过则所有最大公约数是x倍数的对都不能选。

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

    std::vector<i64> g(n + 1);
    for (int i = 1; i <= n; ++ i) {
    	for (int j = i + i; j <= n; j += i) {
    		cnt[i] += cnt[j];
    	}
    }

    for (int i = n; i >= 1; -- i) {
    	g[i] = cnt[i] * (cnt[i] - 1) / 2;
    	for (int j = i + i; j <= n; j += i) {
    		g[i] -= g[j];
    	}
    }

    for (int i = 1; i <= n; ++ i) {
    	if (st[i]) {
    		for (int j = i; j <= n; j += i) {
    			g[j] = 0;
    		}
    	}
    }

    i64 ans = std::accumulate(g.begin(), g.end(), 0ll);
    std::cout << ans << "\n";
}
posted @   maburb  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示