Codeforces Round #383 (Div. 2)

本文解析了四道经典的编程题目,包括快速查找算法、最短周期路径、分组背包问题等,提供了完整的代码实现和思路分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <map>
#include <set>
#include <vector>
using namespace std;

typedef long long ll;
const int qq = 1e5 + 10;
int num[5] = {8, 4 , 2, 6};

int main(){
	int n; scanf("%d", &n);
	if(n == 0){
		printf("1\n");
		return 0;
	}
	printf("%d\n", num[(n-1)%4]);
	return 0;
}

B

统计和查询

类似于前缀

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <map>
#include <set>
#include <vector>
using namespace std;

typedef long long ll;
const int qq = 1e7 + 10;
ll num[qq];
ll vis[qq];
map<int, int> Q;

int main(){
	ll n, x; scanf("%lld%lld", &n, &x);
	for(int i = 1; i <= n; ++i)
        scanf("%lld", num+i);
    ll sum = 0;
    for(int i = 1; i <= n; ++i){
        if(Q.find(x^num[i]) != Q.end()) sum += Q[x^num[i]];
        Q[num[i]]++;
    }
    printf("%lld\n", sum);
	return 0;
}

C

我到今天才理解题意...

找一个最小的t, 从一个点x走t次到达点y那么你走t的话一定要到达x, 也就是说你每次只能走t次, 而且对于x->y 一定存在 y->x

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <map>
#include <set>
#include <vector>
using namespace std;

typedef long long ll;
const int qq = 100 + 10;
int vis[qq];
int id[qq];
int n;

int gcd(int a, int b){
	return b==0?a:gcd(b, a%b);
}

int lcm(int a, int b){
	return a/gcd(a, b)*b;
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%d", id+i);
		vis[id[i]]++;
	}
	bool flag = true;
	for(int i = 1; i <= n; ++i)
		if(vis[i] == 0)	flag = false;
	if(!flag){
		printf("-1\n");
		return 0;
	}
	int minx = 1;
	memset(vis, 0, sizeof(vis));
	for(int i = 1; i <= n; ++i){
		if(vis[i])	continue;
		int start = i;
		int p = i;
		int count = 1;
		vis[p] = 1;
		while(vis[id[p]] != 1){
			vis[id[p]] = 1;
			p = id[p];
			++count;
		}
		if(id[p] == start){
			minx = lcm(minx, count);
		}else{
			printf("-1\n");
			return 0;
		}
	}
	printf("%d\n", minx);
	return 0;
}


D

一个很裸的分组背包

并查集找联通块分组, 然后直接dp

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <map>
#include <set>
#include <vector>
using namespace std;

typedef long long ll;
const int qq = 1e3 + 10;
ll num[qq];
ll pre[qq];
ll n, m, k;
ll w[qq], b[qq];
int find(int x){
	return pre[x]==x?x:pre[x]=find(pre[x]);
}

vector<ll> vw[qq], vb[qq];
ll dp[qq];

int main(){
	scanf("%lld%lld%lld", &n, &m, &k);
	for(int i = 0; i < n; ++i)	scanf("%lld", w+i);
	for(int i = 0; i < n; ++i)	scanf("%lld", b+i);
	for(int i = 0; i <=n; ++i)	pre[i] = i;
	for(int i = 0; i < m; ++i){
		int a, b;scanf("%d%d", &a, &b);
		a--,b--;
		int x = find(a), y = find(b);
		if(x == y)	continue;
		pre[y] = x;
	}
	queue<int> Q[qq];
	for(int i = 0; i < n; ++i)
		Q[find(i)].push(i);
	int p = 0;
	for(int i = 0; i < n; ++i){
		if(Q[i].size() == 0)	continue;
		ll sum1, sum2;
		sum1 = sum2 = 0;
		while(!Q[i].empty()){
			vw[p].push_back(w[Q[i].front()]);
			vb[p].push_back(b[Q[i].front()]);
			sum1 += w[Q[i].front()];
			sum2 += b[Q[i].front()];
			Q[i].pop();
		}
		vw[p].push_back(sum1);
		vb[p].push_back(sum2);
		p++;
	}
	memset(dp, -1, sizeof(dp));
	dp[0] = 0;
	for(int i = 0; i < p; ++i)
		for(int j = k; j >= 0; --j)
			for(int l = 0; l < (ll)vw[i].size(); ++l){
				if(j-vw[i][l] < 0)	continue;
				if(dp[j-vw[i][l]] != -1)
					dp[j] = max(dp[j], dp[j-vw[i][l]]+vb[i][l]);
			}
	ll maxn = -1;
	for(int i = 0; i <= k; ++i)	maxn = max(maxn, dp[i]);
	printf("%lld\n", maxn);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值