CSP-J模拟赛补题2

日期:2024年10月2日

学号:S14738

一、我的总分:
T1【下棋(chess)】:70分

T2【汪洋(BigWater)】:0分

T3【删数(delnum)】:0分

T4【平分糖果(candy)】:0分

二、比赛概况:
T1【下棋(chess)】: 

        题目不算很难,有思路,也实现出来了,但是忽略了数据大小应该用long long,所以只得了70分,最后的30%数据应该是比较大。

T2【汪洋(BigWater)】:

        感觉是要用dfs解决,写完调试的时候发现不太行,可能是死循环了,具体没看出来,然后就直接cout了,最后也是没时间再思考了。

T3【删数(delnum)】:

        感觉需要暴力枚举,但是数据太大了(谁会在数据最大10^9的时候暴力枚举),所以我先判断一下有没有删连续数列的,这样的会好算一些,关键是没有……所以就0分了。

T4【平分糖果(candy)】:

        时间不太够了,也没再仔细读题,觉得美味程度如果是奇数个就不行,简单蒙了一点代码,也没对,应该是格式的问题吧。

三、比赛分析:

T1【下棋(chess)】:

1、题目大意

        Meowowco 最近沉迷下棋。
        众所周知,棋盘上一局有 n 个玩家一起游戏。
        我们的棋子称为”英雄”,英雄分为1、2、3星。1 个 3 星英雄可以由 3 个 2 星英雄合成,1 个 2 星英雄可以由 3 个 1 星英雄合成。
        现在给出每名玩家的英雄阵容,我们定义阵容强度为 18x + 3y + z,其中 x 为 3 星英雄个数,y 为两星英雄个数,zz 为一星英雄个数,其中可以用低星英雄合成高星英雄后再计算阵容强度。
        根据玩家的阵容强度,将玩家序号进行排序,并按阵容强度从大到小的顺序输出玩家的序号(若阵容强度相同,则把玩家序号(第i个输入的玩家序号为i)小的排在前面)。

2、考试思路

        输入 -> 分别计算1、2、3星英雄个数(运用 % 和 / ) -> 排序 -> 输出

3、讲解后思路

        和我的思路差不多,只不过变量和结构体都要用long long类型

4、AC代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
//必须用 long long 类型,没有用就会像我一样得 70分 
long long n;
struct node{
	long long i,str;
}ply[100005];
//sort函数 
bool cmp(node a,node b){
	//题目要求阵容强度从大到小排序,阵容强度相同则把序号小的排在前面 
	if(a.str == b.str){
		return a.i < b.i;
	}
	return a.str > b.str;
}
int main(){
//	freopen("chess.in","r",stdin);
//	freopen("chess.out","w",stdout);
	cin >> n;
	for(int j = 1;j <= n;j++){
		long long x,y,z;
		cin >> z >> y >> x;
		//1个3星英雄可以由3个2星英雄合成
		y+=z/3;
		z%=3;
		//1个2星英雄可以由3个1星英雄合成
		x+=y/3;
		y%=3;
		ply[j].i = j;
		//计算阵容强度 
		ply[j].str = x*18+y*3+z;
	}
	//排序 
	sort(ply+1,ply+1+n,cmp);
	for(int j = 1;j <= n;j++){
		cout << ply[j].i << " ";
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

T2【汪洋(BigWater)】:

1、题目大意

        Meowowco 连夜坐飞机去参加上海国家会展中心的 BilibiliWorld 2023,可是到现场时,已经是一片汪洋。。。

        就算是这样,Meowowco 也不算白来一趟,因为场馆里还有许多可爱的 coser,她可以和这些coser一起合影,然后发说说羡慕她那可怜的队友。

        场馆可以看成一张由n×n个格子构成的矩阵。场馆内的格子可能被水淹没,Meowowco趟水走过去可能会影响心情,因此这些格子上的值为 负数。但是另外的一些格子上站着可爱的 coser,如果 Meowowco 可以与那些 coser合影,那么她就会变得开心,因此这些格子的值为 正数。
        Meowowco 最开始的心情为 100 点,她在逛 BW 的过程中:
                如果走到值为正数的格子,说明可以和可爱的coser拍照,因此会增加心情。
                如果走到值为负数的格子,说明Meowowco需要趟水,因此心情值会下降。
        Meowowco 从 (1,1) 点向右出发,即朝 (1,2)点出发,她每次移动只能移动到一个相邻的格子,并且她需要按照下面的路线逛一圈:
                沿着上一步的方向继续移动
                进行顺时针 90 度转向(注意不可以在同一个格子内连续转向)
                不再逛那些逛过的格子(除了起点)
        其中转向指的是:如果上一步向右走,那么转向之后则为向下走;如果上一步向左走,那么转向之后则为向上走……
        那么逛完 BW 之后,肯定是要从 (1,1) 点离开然后回家的,那么问题来了,Meowowco离开时心情值最大是多少。

2、考试思路

        感觉要用dfs吧,没什么明确的思路

3、讲解后思路

        由于规定了转向,所以Meowowco的路线应该是一个矩形,具体思路如下:

                输入 -> 计算行列前缀和 -> 枚举答案 -> 输出

4、AC代码

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e3+5;
int n,a[N][N],row[N][N],col[N][N],ans;
int main(){
//	freopen("BigWater.in","r",stdin);
//	freopen("BigWater.out","w",stdout);
	cin >> n;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			cin >> a[i][j];
			//计算行列前缀和 
			row[i][j] = row[i][j-1]+a[i][j];
			col[i][j] = col[i-1][j]+a[i][j];
		}
	}
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			//比较 ans和矩形四边长度和,记得减去重复的四个点 
			ans = max(ans,row[1][j]+row[i][j]+col[i][1]+col[i][j]-a[1][j]-a[i][1]-a[1][1]-a[i][j]);
		}
	}
	cout << ans+100;
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

T3【删数(delnum)】:

1、题目大意

        有一个集合,初始状态里面有数字 1、2、3、4、5……114514^​1919810,你可以理解为很多正整数。

        现在给你一个长度为 n 数组a (1≤a​i≤10^9​​ ),每次操作将当前集合中第 a​1小、第a​2小……第a​n小的数同时移除。

        现在有 q 次询问,每次询问包含一个整数 x,查询从初始状态到删除 x 需要操作多少次。若无法删除,输出 0。​​

2、考试思路

        我不会啊,所以纯蒙代码

3、讲解后思路

        输入 -> 删除比x小的并判断x该不该删除 -> 输出

4、AC代码

#include<iostream>
#include<cstdio>
using namespace std;
long long n,q,a[100005];
long long fun(long long x){
	long long ans = 0;
	//找到第一个大于等于x的数 
	long long idx = lower_bound(a+1,a+1+n,x)-a;
	//没找到就从n开始计算
	//找到了但不是x就从idx-1开始计算 
	if(idx == n+1 || a[idx] != x){
		idx--;
	}
	for(int i = idx;i >= 1;i--){
		if(x < a[i]){
			continue;
		}
		//如果刚好到 a[i] 一定能够删除 
		if((x-a[i])%i == 0){
			return ans+(x-a[i])/i+1;
		}
		long long num = (x-a[i])/i+1;
		ans+=num;
		x-=num*i;
	}
	return -1;
}
int main(){
//	freopen("delnum.in","r",stdin);
//	freopen("delnum.out","w",stdout);
	cin >> n;
	for(int i = 1;i <= n;i++){
		cin >> a[i];
	}
	cin >> q;
	while(q--){
		long long x;
		cin >> x;
		long long ans = fun(x);
		//若无法删除,输出0 
		if(ans == -1){
			cout << 0;
		}else{
			cout << ans; 
		}
		cout << endl;
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

T4【平分糖果(candy)】:

1、题目大意

        小可的妈妈给了小可很多的糖果,已经糖果都有美味程度,美味程度用1~6的整数表示。

        有一天达达来小可家做客,小可要把糖果分给达达,现在已知了美味程度为 i 的糖果有 a[i] 个,请问小可能不能把糖果平分成美味程度之和相同的两部分。

2、考试思路

        我还是不太会啊,也就只能蒙代码

3、讲解后思路

        这道题是动规,也就是dp,但是我没学过啊啊啊

                输入 -> 计算美味程度之和 -> 判断(美味程度之和/2)是否能被组成 -> 输出

4、AC代码

#include<iostream>
#include<cstdio>
using namespace std;
long long a[10],cnt;
bool dp[200005];
bool pd(){
	//计算美味程度总和 
	long long m = a[1]+a[2]*2+a[3]*3+a[4]*4+a[5]*5+a[6]*6;
	//如果美味程度总和是奇数,则不可能平分成两个整数 
	if(m%2 == 1){
		return false;
	}
	m/=2;
	for(int i = 0;i <= m;i++){
		dp[i] = false;
	}
	dp[0] = true;
	//for循环判断美味程度总和 dp[j]是否能被构成 
	for(int t = 1;t <= 6;t++){
		for(int i = 1;i <= a[t];i*=2){
			for(int j = m;j >= i*t;j--){
				dp[j] = dp[j] || dp[j-i*t];
			}
			if(dp[m]){
				return true;
			}
		}
	}
	return false;
}
int main(){
//	freopen("candy.in","r",stdin);
//	freopen("candy.out","w",stdout);
	while(cin >> a[1]){
		for(int i = 2;i <= 6;i++){
			cin >> a[i];
		}
		if(a[1]+a[2]+a[3]+a[4]+a[5]+a[6] == 0){
			break;
		}
		cnt++;
		cout << "Collection #"<< cnt << ":" << endl;
		//按照题目要求输出,记住有两次换行 
		if(pd()){
			cout << "Can be divided." << endl << endl;
		}else{
			cout << "Can't be divided." << endl << endl;
		}
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

四、反思&总结:

        和上次一样,嗯…就是数组、变量、结构体什么的尽量开大,注意数据大小是否要用long long类型,最后检查一下输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值