牛客周赛 Round 77

A. 时间表

输出即可。

点击查看代码
void solve() {
	std::string s[] = {"20250121", "20250123", "20250126", "20250206", "20250208", "20250211"};
    int n;
    std::cin >> n;
    std::cout << s[n - 1] << "\n";
}

B. 数独数组

题意:一个数组的任意一个长度为9的连续子数组都是19的排列。有没有一种摆放方式符合。

我们应该{1,2,...,8,9,1,2...}这样循环摆下去,才能保证最多的子数组满足,那么每个数组的出现次数要么是n9,要么是n9

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

    for (int i = 1; i <= 9; ++ i) {
    	if (cnt[i] != n / 9 && cnt[i] != (n + 8) / 9) {
    		std::cout << "NO\n";
    		return;
    	}
    }

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

C. 小红走网格

题意:一个网格里,每次分别可以往上下左右走对应的a,b,c,d步,问能不能到(x,y)

其实是k1a+k2b=y,k3c+k4d=x,那么要求gcd(a,b)|ygcd(c,d)|x

点击查看代码
void solve() {
    int x, y, a, b, c, d;
    std::cin >> x >> y >> a >> b >> c >> d;
    if (y % std::gcd(a, b) == 0 && x % std::gcd(c, d) == 0) {
    	std::cout << "YES\n";
    } else {
    	std::cout << "NO\n";
    }
}

D. 隐匿社交网络

题意:n个数,如果两个数之间二进制下有一位上都是1,那么他们就是一个集合的,问最大的集合有多少人。

明显是并查集,以每一位为一个集合,对应每个数合并其所有1的位的集合就行。

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

    std::vector<int> fa(60), cnt(60, 0);
    std::iota(fa.begin(), fa.end(), 0);

    std::function<int(int)> find = [&](int x) -> int {
    	return x == fa[x] ? x : fa[x] = find(fa[x]);
    };

    for (int i = 0; i < n; ++ i) {
    	i64 x = -1;
    	for (i64 j = 0; j < 60; ++ j) {
    		if (a[i] >> j & 1) {
    			if (x == -1) {
    				x = j;
    			} else {
    				if (find(x) == find(j)) {
    					continue;
    				}
    				cnt[find(x)] += cnt[find(j)];
    				fa[find(j)] = find(x);
    			}
    		}
    	}

    	cnt[find(x)] += 1;
    }

    int ans = 0;
    for (int i = 0; i < 60; ++ i) {
    	if (find(i) == i) {
    		ans = std::max(ans, cnt[i]);
    	}
    }
    std::cout << ans << "\n";
}

E. 1or0

题意:一个01串,每次问一个区间,回答这个区间有多少个子区间至少有11

我们记lasti为左边离i最近的1的位置,sumi=j=1ilasti。记sufi为右边离i最近的1的位置。
那么当询问一个区间[l,r]时,我们可得sumrsuml1,但这个计算得答案区间左端点会在l左边,所以我们要减去这种情况,那么看lastlsufl在哪,那么lastil之后的有rl+1(sufll)个,在l之前的有sufll个,要减去的贡献为(rl+1(sufl1l))(l1)+(sufll)lastl

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

    	sum[i] = sum[i - 1] + last[i];
    }

    std::vector<i64> suf(n + 2, n + 1);
    for (int i = n; i >= 1; -- i) {
    	if (s[i - 1] == '0') {
    		suf[i] = suf[i + 1];
    	} else {
    		suf[i] = i;
    	}
    }

    int q;
    std::cin >> q;
    while (q -- ) {
    	i64 l, r;
    	std::cin >> l >> r;
    	i64 ans = sum[r] - sum[l - 1];
    	i64 L = last[l], R = std::min(r + 1, suf[l]);
    	ans -= ((i64)r - l + 1 - (R - l)) * (l - 1);
    	ans -= ((i64)R - l) * L;
    	std::cout << std::max(0ll, ans) << "\n";
    }
}

F. 计树

题意:一棵树,会随机从集合里选两个点,问每个点可能是这两个点的lca的情况有多少种。

考虑树形dpfu表示答案,cntu表示以u为根的子树下有多少个可选点。那么一个让u每个子树单独考虑,只要两个点在不同的子树下那么lca就是u,那么答案是让每个子树的可选点两两相乘,我们知道i=1nj=1naiaj=(i=1nai)2,那么我们要求的答案就是(vucntv)2vucntv2,如果u本身就是可选点,还有加上vcntv以及加上两个点都选自己的情况。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<std::vector<int> > adj(n);
    for (int i = 1; i < n; ++ i) {
    	int u, v;
    	std::cin >> u >> v;
    	-- u, -- v;
    	adj[u].push_back(v);
    	adj[v].push_back(u);
    }

    int k;
    std::cin >> k;
    std::vector<int> a(n);
    for (int i = 0; i < k; ++ i) {
    	int x;
    	std::cin >> x;
    	-- x;
    	a[x] = 1;
    }

    std::vector<i64> f(n), cnt(n);
    auto dfs = [&](auto self, int u, int fa) -> void {
    	i64 sum = 0;
    	for (auto & v : adj[u]) {
    		if (v == fa) {
    			continue;
    		}

    		self(self, v, u);
    		cnt[u] += cnt[v];
    		sum += cnt[v] * cnt[v];
    	}

    	f[u] = (cnt[u] * cnt[u] - sum) + cnt[u] * a[u] * 2 + a[u];
    	cnt[u] += a[u];
    };

    dfs(dfs, 0, -1);
    for (int i = 0; i < n; ++ i) {
    	std::cout << f[i] << " \n"[i == n - 1];
    }
}
posted @   maburb  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示