2025CCPC郑州邀请赛

这是正式开始练习团队赛的的第一场。本场难度适中,但是教育意义很好。对去年的我们很有挑战,赛后认为对当时没太大意义没补。本次打完之后收获颇多。在vp的过程中第5、6题均有出现题目理解错误的情况,需调整!!

本场链接:Attachments - 2025 National Invitational of CCPC (Zhengzhou)

Problem F. 幻形之路

本题是个搜索问题,赛时思路还是比较清晰。开始通过推导我想到标记后二重暴力取最小值,只是我们都在担心可能会超时。前面的还没敲完我又提议使用多源BFS,因为没看清题意导致一直错误,后边也没返回使用暴力的方法。

  • 先从左上搜索,把左上#放到队列中(如果搜通直接0)

  • 从右下搜索,将右下#进行标记

  • 之后有两种处理方式

    • 多源BFS,如果碰到右下#就直接弹出
    • 双重循环暴力搜索两边的点取距离最小值
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
#define fi first
#define se second 
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
// const int mod = 998244353;
const int mod = 1e9+7;
const int INF = 1e18;
const int N = 1e6+5;
int n,m;
string s;
int dx[]={0,-1,0,1};
int dy[]={-1,0,1,0};
struct p
{
	int st;
	int x,y;
};
void solve()
{
	cin >> n >> m;
	vector<vector<char>> a(n+5,vector<char>(m+5));
	vector<vector<bool>> vi(n+5,vector<bool>(m+5));
	auto mp=vi; // 标记后#
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++) cin >> a[i][j];
		
	queue<p> q,q1;
	q.push({1,1,1});// 左上开始搜
	while(q.size())
	{
		auto cu=q.front(); q.pop();
		int st=cu.st,x=cu.x,y=cu.y;
		if(x==n&&y==m)//搜通直接退出
		{
			cout << 0 << endl;
			return;
		}
		if(a[x][y]=='#')//左上的源点放入q1
		{
			q1.push({1,x,y});
			continue;
		}
		for(int i=0; i<4; i++)
		{
			int tx=x+dx[i];
			int ty=y+dy[i];
			if(tx<1||ty<1||tx>n||ty>m||vi[tx][ty]) continue;
			vi[tx][ty]=1;
			q.push({st+1,tx,ty});
		}
	}
	for(int i=1; i<=n; i++) fill(all(vi[i]),0);
	
	q.push({1,n,m});//右下开始搜
	while(q.size())
	{
		auto cu=q.front(); q.pop();
		int st=cu.st,x=cu.x,y=cu.y;
		if(a[x][y]=='#')//标记终点#
		{
			mp[x][y]=1;
			continue;
		}
		for(int i=0; i<4; i++)
		{
			int tx=x+dx[i];
			int ty=y+dy[i];
			if(tx<1||ty<1||tx>n||ty>m||vi[tx][ty]) continue;
			vi[tx][ty]=1;
			q.push({st+1,tx,ty});
		}
	}
	
	for(int i=1; i<=n; i++) fill(all(vi[i]),0);
	while(q1.size())// 多源BFS
	{
		auto cu=q1.front(); q1.pop();
		int st=cu.st,x=cu.x,y=cu.y;
		if(mp[x][y])//找到右下#
		{
			cout << st << endl;
			return ;
		}
		for(int i=0; i<4; i++)
		{
			int tx=x+dx[i];
			int ty=y+dy[i];
			if(tx<1||ty<1||tx>n||ty>m||vi[tx][ty]) continue;
			vi[tx][ty]=1;
			q1.push({st+1,tx,ty});
		}
	}
}
signed main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int T=1;
	cin >> T;
	while(T--) solve();
	return 0;
}

Problem M. 川陀航空学院

  • 并查集模板。
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
#define fi first
#define se second 
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
// const int mod = 998244353;
const int mod = 1e9+7;
const int INF = 1e18;
const int N = 1e6+5;
int n,m;
string s;
vector<int> p(N),sz(N);
int find(int x)
{
	if(x!=p[x]) p[x]=find(p[x]);
	return p[x];
}
void unite(int x, int y)
{
	x=find(x),y=find(y);
	if(x==y) return ;
	if(sz[x]>sz[y]) swap(x,y);
	p[x]=y;
	sz[y]+=sz[x];
}
void solve()
{
	cin >> n >> m;
	int ans=0;
	for(int i=1; i<=n; i++) p[i]=i,sz[i]=1;
	for(int i=0; i<m; i++)
	{
		int u,v;
		cin >> u >> v;
		if(find(u)==find(v)) ans++;
		else unite(u,v);
	}
	int cnt=0;
	for(int i=1; i<=n; i++) cnt+=(p[i]==i);//联通块个数
	ans+=cnt-1;
	cout << ans << endl;
}
signed main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int T=1;
	// cin >> T;
	while(T--) solve();
	return 0;
}

Problem H. 树论函数

  • 公式推导、打表

原公式: f ( n ) = f ( a ) ⋅ f ( b ) f(n)=f(a)·f(b) f(n)=f(a)⋅f(b)。

f ( a ) ⋅ f ( a + 1 ) = a ( a + 1 ) ( a + 1 ) ( a + 2 ) f(a)·f(a+1)=a(a+1)(a+1)(a+2) f(a)⋅f(a+1)=a(a+1)(a+1)(a+2)
= a ( a + 2 ) ( a + 1 ) ( a + 1 ) =a(a+2)(a+1)(a+1) =a(a+2)(a+1)(a+1)
= ( a 2 + 2 a ) ( a 2 + 2 a + 1 ) =(a^2+2a)(a^2+2a+1) =(a2+2a)(a2+2a+1)

设 b = a 2 + 2 a b=a^2+2a b=a2+2a

有 f ( b ) = f ( a ) ⋅ f ( a + 1 ) f(b)=f(a)·f(a+1) f(b)=f(a)⋅f(a+1)

则任意相邻节点都有某个点和他们相连接,所以所有的点都是相连的

  • 既然所有都相连,直接输出区间长度即可

Problem E. 双生魔咒

  • 字符串哈希

本题可用字符串/字典树解决,在这介绍字符串哈希的解法。

  • 要使前缀尽量多,肯定要先进行排序。字符串的排序就是从头到尾对比相似度。

  • 其次涉及到如何存的问题。

    • 如果把所有字符串的所有前缀都存起来那么是会超内存的,并且字符串的比较也是很慢,还会超时间

字符串哈希会把字符串映射成对应的哈希值,存储数字一个只有8字节,并且比较操作也很快。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
#define fi first
#define se second 
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
#define ull unsigned long long
// const int mod = 998244353;
const int mod = 1e9+7;
const int INF = 1e18;
const int N = 1e6+5;
int n,m;
string s;
const int P=131;
void solve()
{
	cin >> n;
	vector<string> a(2*n+1);
	for(int i=1; i<=2*n; i++) cin >> a[i];
	sort(a.begin()+1,a.end()); 
	unordered_map<int,int> mp;
	int cnt=0;
	for(int i=1; i<=2*n; i+=2)
	{
		ull cu=0;
		string k=' '+a[i];
		for(int j=1; j<k.size(); j++)
		{
			cu=cu*P+k[j];
			mp[cu]++;
		} 
	}
	for(int i=2; i<=2*n; i+=2)
	{
		ull cu=0;
		string k=' '+a[i];
		for(int j=1; j<k.size(); j++)
		{
			cu=cu*P+k[j];
			if(mp.count(cu)) cnt+=mp[cu];
		}
	}
	cout << cnt << endl;
}
signed main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int T=1;
	// cin >> T;
	while(T--) solve();
	return 0;
}
相关推荐
少许极端2 小时前
算法奇妙屋(四十八)-单调栈
java·算法·单调栈
HERR_QQ2 小时前
端到端课程自用 2课 动静态感知decoder
笔记·学习·自动驾驶
水木流年追梦2 小时前
CodeTop Top 300 热门题目2-最长回文子串
开发语言·人工智能·python·算法·leetcode
图码2 小时前
递归入门:从n到1的优雅打印之旅
数据结构·c++·算法·青少年编程·java-ee·逻辑回归·python3.11
大肥羊学校懒羊羊2 小时前
题解:计算约数个数
数据结构·c++·算法
ximu_polaris2 小时前
设计模式(c++)-结构型模式-装饰器模式
c++·设计模式·装饰器模式
Queenie_Charlie2 小时前
二叉树_
c++·二叉树·简单树结构
生信之灵2 小时前
拓扑与曲率双剑合璧:scGeom如何从单细胞数据中“看见”细胞命运
人工智能·深度学习·算法·单细胞·多组学
良木生香2 小时前
【C++初阶】:STL——String从入门到应用完全指南(3)
c语言·开发语言·数据结构·c++·算法