首页 > 编程语言 >2022“杭电杯”中国大学生算法设计超级联赛(7)

2022“杭电杯”中国大学生算法设计超级联赛(7)

时间:2022-08-17 10:33:10浏览次数:86  
标签:return 联赛 sum pos dfs 2022 ans 杭电杯 LL

比赛链接:

https://vjudge.net/contest/509567

B - Independent Feedback Vertex Set

题意:

定义无向无环图为森林,集合中任意两点之间没有边相连的集合为独立集。
现在有 \(n\) 个点,每个点有一个权重,刚开始的图中有 1,2,3 三个点,互相之间有边相连。
按照给定的顺序依次添加点进入集合,每次告诉图中的一条边 \((y, z)\),然后向集合中加入点 \(x\),加入边 \((x, y), (x, z)\)。
从最后形成的图中找出一个独立集,使得剩下的图为森林,问这个独立集的权重最大为多少。

思路:

对于每一个新加入的点,它与图中选定的那条边的两个点不会同时选中,即 \(x\) 不会和 \(y, z\) 同时选中。
考虑染色,先将初始的三个点染不同的颜色,接下来加入的每个点就都有指定的颜色,求同一种颜色的权值之和的最大即可。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL n;
	cin >> n;
	vector <LL> a(n);
	for (int i = 0; i < n; i ++ )
		cin >> a[i];
	vector <LL> color(n);
	for (int i = 0; i < 3; i ++ )
		color[i] = i;
	for (int i = 3; i < n; i ++ ){
		LL u, v;
		cin >> u >> v;
		u -- ; v -- ;
		color[i] = 3 - color[u] - color[v];
	}
	vector <LL> ans(3, 0);
	for (int i = 0; i < n; i ++ )
		ans[color[i]] += a[i];
	cout << *max_element(ans.begin(), ans.end()) << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T = 1;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}

C - Counting Stickmen

题意:

在给定的树中找有几个下图红色节点所示的火柴人。

思路:

每个节点的度数减去 1 就是它作为手臂的可能,度数大于 2 的节点,它作为身体的可能为 \(C_{deg[i] - 1}^2\) 种,即减去连接边,剩余的节点选两个作为腿。
接着枚举每个点作为身体中心,计算火柴人的数量。
选择一个身体,两个手臂,除去两个手和身体,其它节点都可以作为头。
对于手,下图这种情况是不行的,要减去。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int P = 998244353;
LL qp(LL a, LL k, LL p){
	LL ans = 1;
	while (k){
		if (k & 1) ans = ans * a % p;
		k >>= 1;
		a = a * a % p;
	}
	return ans;
}
LL inv(LL x){
	return qp(x, P - 2, P);
}
LL c2(LL x){
	return x * (x - 1) % P * inv(2) % P;
}
void solve(){
	LL n;
	cin >> n;
	vector <LL> g[n + 1], deg(n + 1);
	for (int i = 0; i < n - 1; i ++ ){
		LL u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
		deg[u] ++ ;
		deg[v] ++ ;
	}
	vector <LL> hand(n + 1), body(n + 1);
	for (int i = 1; i <= n; i ++ ){
		hand[i] = deg[i] - 1;
		if (deg[i] > 2){
			body[i] = c2(deg[i] - 1);
		}
	}
	LL ans = 0;
	function<void(LL, LL)> dfs = [&](LL u, LL fa){
		LL h = 0, b = 0;
		for (auto v : g[u]){
			h = (h + hand[v]) % P;
			b = (b + body[v]) % P;
			if (v == fa) continue;
			dfs(v, u);
		}
		if (deg[u] < 4) return;
		LL res = 0;
		for (auto v : g[u])
			res = (res + body[v] * ((c2(h - hand[v]) - (b - body[v])) % P + P) % P * (deg[u] - 3) % P ) % P;
		ans = (ans + res) % P;
	};
	dfs(1, 0);
	cout << ans << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T = 1;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}

D - Black Magic

题意:

有四种方块:
E:左右两面全是白色
L:右边是黑色,右边是白色
R:左边是黑色,左边是白色
B:左右两面都是黑色
当黑面和黑面碰在一起的时候,这两个方块可以融合,问最小/最大的连通块是多少。

思路:

就分类讨论一下。
最小即将 \(L\) 和 \(R\) 组合,然后 \(B\) 合到其中一个上,如果 \(L\) 和 \(R\) 都没有的话,则单独算一个。
最大就是将 \(L\) 放到左边,\(R\) 放到右边,然后 \(E\) 和 \(B\) 交替。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL E, L, R, B;
	cin >> E >> L >> R >> B;
	LL minn = E;
	if (min(L, R) >= 1){
		minn += max(L, R);
	}
	else{
		minn += L + R;
		if (max(L, R) == 0) minn += (B > 0);
	}
	LL maxn = L + R;
	if (B > E){
		maxn += E * 2 + 1;
	}
	else{
		maxn += B + E;
	}
	cout << minn << " " << maxn << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T = 1;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}

F - Sumire

题意:

计算 \(\sum_{i = l}^r f^k (i, B, d)\)。
\(f(i, B, d)\) 表示在 \(x\) 的 \(B\) 进制下,\(d\) 出现的次数。
在本题中 \(0^0 = 0\)。

思路:

显然的数位 \(dp\)。
定义 \(dp[pos][sum][limit][zero]\) 表示枚举到第 \(pos\) 位,\(d\) 出现了 \(sum\) 次,\(limit\) 为 1 表示当前枚举的数为上限,\(zero\) 为 1 表示有前导 0。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int P = 1e9 + 7;
LL k, B, d, l, r, dp[70][70][2][2], num[70];
LL qp(LL a, LL k, LL p){
	if (!a && !k) return 0;  // 0 的 0 次为 0
	LL ans = 1;
	while (k){
		if (k & 1) ans = ans * a % p;
		k >>= 1;
		a = a * a % p;
	}
	return ans;
}
LL dfs(int pos, LL sum, int limit, int zero){
	if (pos == 0) return dp[pos][sum][limit][zero] = qp(sum, k, P);
	if (dp[pos][sum][limit][zero] != -1) return dp[pos][sum][limit][zero];
	LL ans = 0;
	int up = (limit ? num[pos] : B - 1);
	if (d == 0){
		if (up == 0) ans = (ans + dfs(pos - 1, sum + !zero, limit, zero)) % P;
		else{
			ans = (ans + dfs(pos - 1, sum, limit, 0)) % P;	//放up
			ans = (ans + dfs(pos - 1, sum + !zero, 0, zero)) % P;	//放d
			ans = (ans + dfs(pos - 1, sum, 0, 0) * (up - 1) % P) % P;	//放其它数
		}
	}
	else{
		if (d < up){
			ans = (ans + dfs(pos - 1, sum, limit, 0)) % P;	//放up(因为 d != 0,所以 up > 1)
			ans = (ans + dfs(pos - 1, sum + 1, 0, 0)) % P;	//放d
			ans = (ans + dfs(pos - 1, sum, 0, zero)) % P;	//放0
			ans = (ans + dfs(pos - 1, sum, 0, 0) * (up - 2) % P) % P;	//放其它数
		}
		else if (d == up){
			ans = (ans + dfs(pos - 1, sum + 1, limit, 0)) % P;	//放d
			ans = (ans + dfs(pos - 1, sum, 0, zero)) % P;	//放0
			ans = (ans + dfs(pos - 1, sum, 0, 0) * (up - 1) % P) % P;	//放其它数
		}
		else {
			ans = (ans + dfs(pos - 1, sum, limit, 0)) % P;	//放limit
			ans = (ans + dfs(pos - 1, sum, 0, zero)) % P;	//放0
			ans = (ans + dfs(pos - 1, sum, 0, 0) * (up - 1) % P) % P;	//放其他数
		}
	}
	return dp[pos][sum][limit][zero] = ans % P;
}
LL solve(LL x){
	memset(dp, -1, sizeof dp);
	int len = 0;
	while(x){
		num[ ++ len] = x % B;
		x /= B;
	}
	return dfs(len, 0, 1, 1);
}
void solve(){
	cin >> k >> B >> d >> l >> r;
	cout << ((solve(r) - solve(l - 1)) % P + P) % P << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T = 1;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}

H - Triangle Game

题意:

两个人轮流玩游戏,给定三角形的三条边 \(a\),\(b\),\(c\),每次可以将其中一条边变小,当有一个人不论怎么修改都构不成三角形的时候,判输,两个人都采取最优策略,问先手是否必胜。

思路:

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL a, b, c;
	cin >> a >> b >> c;
	if ( (a - 1) ^ (b - 1) ^ (c - 1) ) cout << "Win\n";
	else cout << "Lose\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T = 1;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}

标签:return,联赛,sum,pos,dfs,2022,ans,杭电杯,LL
From: https://www.cnblogs.com/Hamine/p/16586257.html

相关文章

  • 2022-8-16 mysql 第二天 约束
    DQL数据库查询语言重点,DQL是我们每天都要接触编写最多也是最难的SQL,该语言用来查询记录,不会修改数据库和表结构。构建数据库创建一张student表:DROPTABLEIFEXISTSst......
  • NOI2022赛前随记
    NOI2022赛前随记想了好久到底应该怎么给这篇不成体统的文章命名,却也无可奈何。明明眼前是短短一望便知的尽头,却不忍心写下"退役记"三个字,大概是为自己的前程感到绝望吧,明......
  • 上网记录20220816
    一个dotnet数据库orm框架 https://github.com/leadnt/FluentDAO一个基于HttpClient的开源项目。只需要定义c#接口并修改相关特性,即可异步调用远程http接口的客户......
  • 【2022杭电多校】第九场 1008 Shortest Path in GCD Graph 【容斥+优化】
    链接https://acm.hdu.edu.cn/showproblem.php?pid=7240题意是有n个点组成的完全图,每个点的权重组成了1-n的排列,点i和点j的距离为\(gcd(i,j)\),给出q组询问,每次询问给出u......
  • vs2022附加到进程调试,设断点无效,或找不到w3wp.exe
    vs2022附加到进程调试,设断点无效,或找不到w3wp.exe1.调试—>选项—>调试,取消勾选“启动仅我的代码”2.原因是iis网站绑定的网站不是debug版本的,发布的时候需要选择debug......
  • 2022-08-16面试
    1.springboot和tomcat2.springcloud的请求如何通过网关鉴权?3.springmvc启动时组件的加载顺序?4.mybatis如何同时更新三条记录5.hibernate实现级联更新6.一个web程序......
  • 2022.34 物联网协议
    物联网的发展离不开互联网,但由于物联网场景复杂多样,设备端硬件规格、网络稳定性、流量限制、功耗等因素造成物联网设备的消息传递与传统互联网场景有着很大不同,也因此产生......
  • 2022-08-16 第六小组 高佳誉 学习笔记
    DQL数据库查询语言重点,DQL是我们每天都要接触编写最多也是最难的SQL,该语言用来查询记录,不会修改数据库和表结构。构建数据库创建一张student表:DROPTABLEIFEXISTSst......
  • 2022-08-16 第十小组 石晓荟
    DQL数据库查询语言单表查询基本查询基本语法查询所有列:select*from表名;select*fromstudent;查询指定的列:selectid,`name`,age,genderfromstudent;sele......
  • 20220816 第一组 于芮 数据库查询(第三十二天)
     小白成长记——第三十二天   今天是学数据库的第二天,学习的内容比昨天要稍微难一点,但是还是很好理解的,知识量很大,需要记忆的很多,很考验脑容量,但是还是要认真学习......