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;
}
相关推荐
洛水水1 分钟前
【力扣100题】36.二叉树展开为链表
算法·leetcode·链表
.YM.Z1 分钟前
C++类和对象(中)
c++·类和对象
lwf0061642 分钟前
PNN (Product-based Neural Network) 学习日记
算法·机器学习
Tairitsu_H4 分钟前
C++:优先队列的模拟实现
开发语言·c++·stl·优先队列
ZPC82105 分钟前
YOLO-3D + 双目相机 (RGB + 深度 + 点云) → 3D 位置 + 抓取姿态
人工智能·算法·计算机视觉·机器人
ZPC82106 分钟前
YOLOv8-3D(3D 目标检测 + 6D 抓取姿态)
算法·机器人
lzh2004091913 分钟前
效率与安全并重:C++ 线程安全
linux·c++
Shan120516 分钟前
RAII妙用:使用标准库的包装器
开发语言·c++
bubiyoushang88820 分钟前
基于 TGLVM 算法的迁移学习分类系统
算法·分类·迁移学习
Hua-Jay22 分钟前
OpenCV联合C++/Qt 学习笔记(十八)----二维码检测及积分图像
c++·笔记·qt·opencv·学习