【ZJCPC2022 第19届 浙江省赛】The 19th Zhejiang Provincial Collegiate Programming Contest

文章包含一系列编程问题的解决方案,涉及数学逻辑、C++实现、字符串处理以及图论中的Dijkstra算法。例如,JBLovesMath问题讨论了求解a等于b的不同方式,B.JBLovesComma涉及在字符串中插入逗号的规则,而EasyGlide问题则需要计算滑翔路径的最短时间,利用了Dijkstra算法。其他问题如C.JBWantstoEarnBigMoney和L.CandyMachine分别涉及数值处理和组合优化。

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

目录

A. JB Loves Math

B.JB Loves Comma

C. JB Wants to Earn Big Money

L. Candy Machine

G. Easy Glide

M. BpbBppbpBB

I. Barbecue

A. JB Loves Math

思路:
a b
要使a = b
则使b-a = 0
1.b-a = 正偶
1.1 (b-a)/2为奇数    则b-a+(b-a)/2+(b-a)/2 = 0
1.2 (b-a)/2为偶数      b-a + (b-a+1)+(b-a+1) - (b-a+2)= 0


2.a-b = 正奇
a-b - (a-b+1) + 1 = 0


3.其他情况比较简单就不讨论了

#include<bits/stdc++.h>
using namespace std ;
const int maxn = 1e3 + 10 ;
const int inf = 0x3f3f3f3f ;
void deal(){
	int a , b ; cin >> a >> b ;
	if(a == b)cout << 0 << endl ;
	else if(a > b){
		if((a-b) % 2 == 0){
			cout << 1 << endl ; 
		}else{
			cout << 2 << endl ; 
		}
	}else{
		if((b - a) % 2 == 1){
			cout << 1 << endl ; 
		}else{
			if((b-a)/2 % 2 == 1)cout << 2 << endl ;
			else cout << 3 << endl ; 
		}
	}
}
int main(){
	int t ; cin >> t ;
	while(t--)deal() ;
	return 0 ;
}

B.JB Loves Comma

#include<bits/stdc++.h>
using namespace std ;
const int maxn = 1e3 + 10 ;
const int inf = 0x3f3f3f3f ;
void deal(){
	string s ; cin >> s ;
	for(int i = 0 ; i < s.size() ; i++){
		cout << s[i] ;
		if(i >= 2 && s.substr(i-2 , 3) == "cjb"){
			cout << "," ;
		}
	}
}
int main(){
	deal() ;
	return 0 ;
}

C. JB Wants to Earn Big Money

#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 1e5 + 10 ;
const int inf = 0x3f3f3f3f ;
void deal(){
	int n , m , x , ans = 0 ; cin >> n >> m >> x ;
	for(int i = 0 ; i < n ; i++){
		int v ; cin >> v ;
		if(v >= x)ans++ ;
	}
	for(int i = 0 ; i < m ; i++){
		int v ; cin >> v ;
		if(v <= x)ans++ ;
	}
	cout << ans << endl ;
}
int main(){
	deal() ;
	return 0 ;
}

L. Candy Machine

思路:假设最终选择的集合的平均数不超过 k。 为使平均数不超过 k,应将 ≤ k 的数全部选入,然后贪心选 择 > k 的部分中最小的若干个数。 因此将 N 个数从小到大排序后,最优解一定是一个前缀。 枚举每个前缀,二分出严格大于平均数的数字个数。

#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 1e6 + 10 ;
const int inf = 0x3f3f3f3f ;
int a[maxn] ;
double sum[maxn] ;
void deal(){
	int n ; scanf("%d" , &n) ;
	for(int i = 1 ; i <= n ; i++){
		scanf("%d" , &a[i]) ;
	}
	sort(a+1 , a+1+n) ;
	for(int i = 1 ; i <= n ; i++){
		sum[i] = a[i] + sum[i-1] ;
	}
	int ans = 0 ;
	for(int i = 1 ; i <= n ; i++){
		double avg = sum[i] / i ;
		int l = 1 , r = i ;
		while(l < r){
			int mid = l+r >> 1 ;
			if(a[mid] > avg)r = mid ;
			else l = mid+1 ;
		}
		ans = max(ans , i-l+1) ;
	}
	cout << ans << endl ;
}
int main(){
	deal() ;
	return 0 ;
}

G. Easy Glide

思路:用结构体存储每一个点,开始点是0点,结束点是n+1点,然后计算i点到j点所花的时间,再用dijkstra算法计算最短时间

注意点:出发点不能加速;数据要开long long。

#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 1e3 + 10 ;
const int inf = 0x3f3f3f3f ;
struct node{
	ll x , y ;
}p[maxn];
double g[maxn][maxn] , d[maxn] ;
int vis[maxn] ;
void deal(){
	int n ; cin >> n ; 
	fill(d , d+maxn , inf) ;
	for(int i = 1 ; i <= n ; i++){
		ll u , v ; scanf("%lld %lld" , &u , &v) ;
		p[i].x = u , p[i].y = v ;
	}
	scanf("%lld %lld %lld %lld" , &p[0].x , &p[0].y , &p[n+1].x , &p[n+1].y) ;
	ll v1 , v2 ; 
	scanf("%lld %lld" , &v1 , &v2) ;
	for(int i = 0 ; i <= n+1 ; i++){
		for(int j = 0 ; j <= n+1 ; j++){
			if(i == j){
				g[i][j] = 0 ;
				continue ;
			}
			double dis = sqrt(abs((p[i].x - p[j].x) * (p[i].x - p[j].x)) + abs((p[i].y - p[j].y) * (p[i].y - p[j].y))) ;
			if(v2*3 >= dis && i != 0){
				g[i][j] = dis/v2 ;
			}else if(v2*3 < dis && i != 0){
				g[i][j] = 3+(dis-v2*3)/v1 ;
			}else{
				g[i][j] = dis/v1 ;
			}
		}
	}
	d[0] = 0 ;
	for(int i = 0 ; i <= n+1 ; i++){
		int t = -1 , mind = 0 ;
		for(int j = 0 ; j <= n+1 ; j++){
			if(!vis[j]){
				if(t == -1 || mind > d[j]){
					t = j ;
					mind = d[j] ;
				}
			}
		}
		if(t == -1)break ;
		vis[t] = 1 ;
		for(int j = 0 ; j <= n+1 ; j++){
			if(!vis[j]){
				d[j] = min(d[j] , d[t]+g[t][j]) ;
			}
		}
	}
	printf("%.6lf\n" , d[n+1]) ;
}
int main(){
	deal() ;
	return 0 ;
}

M. BpbBppbpBB

假设黑色格子数为cnt1 , 白色格子组成的洞数为cnt2 , 而C印章数为a , S印章数为b

C印章的黑色格子数为146,S印章的黑色格子数为100 

C印章的白洞为2,S印章的白洞为1

则a*146 + b*100 = cnt1 , a*2+b = cnt2

所以只要求出cnt1,cnt2,然后解方程就好了

如何判断是否是白洞呢?

我是先用bfs计算出一个白色连通块中白色格子的个数 == 12,且该白色连通块的形状是4*4的(可以自己比划一下,用俩个印章拼接是组不出4*4的白色连通块且其中白色格子的个数 == 12的)

#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 1e3 + 10 ;
const int inf = 0x3f3f3f3f ;
char c[maxn][maxn] ;
int vis[maxn][maxn] ;
int X[4] = {1 , 0 , -1 , 0} ;
int Y[4] = {0 , 1 , 0 , -1} ;
int n , m ;
struct node {
	int x , y ;
};
bool bfs(int x , int y){
	queue<node > q ;
	node temp ;
	temp.x = x , temp.y = y ;
	q.push(temp) ;
	vis[x][y] = 1 ;
	int cnt = 0 ;
	int maxx = x , maxy = y , minx = x , miny = y ; 
	while(!q.empty()){
		node top = q.front() ;
		q.pop() ;
		cnt++ ;
		for(int i = 0 ; i < 4 ; i++){
			int nx = top.x + X[i] ;
			int ny = top.y + Y[i] ;
			if(vis[nx][ny] == 0 && c[nx][ny] == '.'){
				if(nx >= 0 && nx < n && ny >= 0 && ny < m){
					vis[nx][ny] = 1 ;
					temp.x = nx , temp.y = ny ;
					q.push(temp) ;
					maxx = max(maxx , nx) ;
					maxy = max(maxy , ny) ;
					minx = min(minx , nx) ;
					miny = min(miny , ny) ;
				}
			}
		}
	}
	if(cnt == 12 && maxx - minx == 3 && maxy - miny == 3)return true ;
	else return false ;
}
void deal(){//C:146 S:100
	cin >> n >> m ;
	int cnt1 = 0 , cnt2 = 0 ;
	for(int i = 0 ; i < n ; i++){
		scanf("%s" , c[i]) ;
		for(int j = 0 ; j < m ; j++){
			if(c[i][j] == '#'){
				cnt1++ ;
			}
		}
	}
	for(int i = 0 ; i < n ; i++){
		for(int j = 0 ; j < m ; j++){
			if(c[i][j] == '.'){
				if(bfs(i , j))cnt2++ ;
			}
		}
	}
	for(int i = 0 ; i <= cnt1/146 ; i++){
		if((cnt1 - 146*i) % 100 == 0){
			for(int j = 0 ; j <= (cnt1 - 146*i)/100 ; j++){
				if(i*2 + j == cnt2){
					cout << i << " " << j << endl ;
					return ;
				}
			}
		}
	}
}
int main(){
	deal() ;
	return 0 ;
}

I. Barbecue

思路:若一开始就是回文串,那就后手赢;若一开始不是回文串,如果这子串不管是掐头还是去尾都是回文串的话,这个子串的情况类似于,ab,abab,ababab,这说明终止态的子串长度一定是偶数,因此输赢只和起始串长度 的奇偶性有关。

        但又因为n = 1e6 , q = 1e6 ,使用一般方法判断是否是回文的时间复杂度是O(n*q),这必然会超时,用字符串哈希判断是否是回文的时间复杂度是O(1),所以我们要用字符串哈希来降低判断是否是回文的时间复杂度。

#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef unsigned long long ULL ;
const int maxn = 1e6 + 10 ;
const int inf = 0x3f3f3f3f ;
const int base = 131 ;
char s[maxn] ;
//h是字符串正序hash值,h1是字符串逆序hash值
ULL p[maxn] , h[maxn] , h1[maxn] ;
int n , m ; 
ULL get(int l , int r){
    return h[r] - h[l-1] * p[r-l+1] ;
}
ULL get1(int l , int r){//求逆序哈希值 
	//因为是从n开始的第l-1个,和第r个 
    return h1[n-l+1] - h1[n-r] * p[r-l+1] ;
}
void deal(){
	scanf("%d %d %s" , &n , &m , s+1) ;
	p[0] = 1 ;
    for(int i = 1 ; i <= n ; i++){
        h[i] = h[i-1] * base + s[i] - 'a' + 1 ;
        h1[i] = h1[i-1] * base + s[n-i+1] - 'a' + 1 ;
        p[i] = p[i-1] * base ;
    }
	for(int i = 0 ; i < m ; i++){
		int l , r ; scanf("%d %d" , &l , &r) ;
		if(get(l , r) == get1(l , r) || ((r-l) & 1)){
			printf("Budada\n") ;
		}else{
			printf("Putata\n") ;
		}
	}
}
int main(){
	deal() ;
	return 0 ;
}

截至目前,尚未有2024年四川省级大学生程序设计竞的具体题目或题解公开发布。然而,可以基于以往的比内容推测可能涉及的类型和主题。 通常情况下,四川省大学生程序设计竞(Sichuan Provincial Collegiate Programming Contest)中的A题往往是一个相对基础但具有挑战性的算法问题,旨在测试参者的逻辑思维能力和编程技巧。例如,在2021年的比中,A题“Chuanpai”的核心在于通过模拟来处理周期性变化的行为模式[^3]。 对于类似的题目,解决的关键通常是识别并利用某种规律或者周期特性来进行高效计算。以下是针对该类问题的一个通用解决方案框架: ### 解决方案框架 假设未来某道A题涉及到周期行为的变化,则可以通过如下方式实现其基本逻辑: #### 周期检测与状态更新 ```python def simulate_rounds(people, preferences): rounds = 0 while not is_stable_state(people): # 判断当前状态是否稳定 update_people_based_on_preferences(people, preferences) # 更新每个人的状态 rounds += 1 return rounds, people def is_stable_state(people): # 定义稳定性条件 pass def update_people_based_on_preferences(people, preferences): n = len(preferences) new_people = [] for i in range(n): if (preferences[i] % 2 == 0 and i % 2 == 0) or \ (preferences[i] % 2 != 0 and i % 2 != 0): new_people.append(add_dish(people[i])) else: new_people.append(eat_dish(people[i])) global people people = new_people[:] def add_dish(person): person['dishes'] += 1 return person def eat_dish(person): if person['dishes'] > 0: person['dishes'] -= 1 return person ``` 上述代码片段展示了如何根据偏好列表`preferences`动态调整人员数组`people`的状态,并持续迭代直到达到某个稳定的终止条件为止。 尽管目前无法确切得知2024年度的确切考题细节,但从过往经验来看,比倾向于考察选手们对数据结构算法优化以及边界情况处理的理解程度。 ### 结论 综上所述,虽然具体到2024年的事详情尚不可知,但是通过对历年真题的学习研究可以帮助预测可能出现的方向及其应对策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值