CSP-J模拟赛2刘彦孜补题

日期:2023.10.2
学号:S06465
一:
总分数:
T1【下棋(chess)】:70
T2【汪洋(BigWater)】:20
T3【删数(delnum)】:20
T4【平分糖果(candy)】:20
二、比赛过程
第一题比较简单,暴力就能过,不过要开long long,我只开了sum的,x,y,z没开,在计算过程中爆int了
第二题用暴搜骗得分
第三题是用的暴力计算、打表
第四题是用的比较暴力的写法
三、比赛分析
T1【下棋(chess)】:
1.题目大意
一共有n组数,每次输入z,y,x,三个z可以合成一个y,三个y可以合成一个x,其中阵容强度为18x+3y+z,让你按阵容强度顺序输出玩家的序号(若阵容强度相同,则按玩家序号排序)
2.比赛中的思考
直接根据题目描述换算,计算总和,最后排一个序就行了,但是我没注意x,y,z,在计算过程中爆int了30分就水灵灵的没了
3.解题思路
根据题目要求换算,计算,最后用sort排一个序,输出就行(一定要注意开long long)
4.AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n;
struct node{
	long long x,y,z;
	long long sum;
	int id;
}a[N];
int cmp(node a,node b){
	if(a.sum==b.sum){
		return a.id<b.id;
	}
	return a.sum>b.sum;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&a[i].z,&a[i].y,&a[i].x);
		a[i].y+=a[i].z/3;
		a[i].z%=3;
		a[i].x+=a[i].y/3;
		a[i].y%=3;
		a[i].sum=18*a[i].x+3*a[i].y+a[i].z;
		a[i].id=i;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		printf("%d ",a[i].id);
	}
	return 0;
}

T2【汪洋(BigWater)】:
1.题目大意
从(1,1)点向右出发,每次移动只能移动到一个相邻的格子,每次可以沿着上一步的方向继续移动,或进行顺时针90度转向,而且不再逛那些逛过的格子(起点除外),最后要回到(1,1),问最大的心情值是多少
2.比赛中的思考
没有什么思路,看了一眼数据,写了一个暴搜偏分
3.解题思路
通过模拟样例可以发现,她每次都是走了一个矩形的边,求出每行每列的前缀和,最后利用前缀和求解就行了
4.AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n;
int a[N][N];
int r[N][N];
int c[N][N];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%d",&a[i][j]);
			r[i][j]=r[i][j-1]+a[i][j];
			c[i][j]=c[i-1][j]+a[i][j];
		}
	}
	int ans=-0x3f3f3f3f;
	for(int i=2;i<=n;i++){
		for(int j=2;j<=n;j++){
			ans=max(ans,r[1][j-1]+c[i-1][j]+r[i][j]+c[i-1][1]);
		}
	}
	printf("%d",ans+100);
	return 0;
}

T3【删数(delnum)】:
1.题目大意
给一个长度为n的数组a,每次操作将第a[1]小、第a[2]小...第a[n]小的数同时移除,有q次询问,问从初始状态到删除x需要操作多少次,如果无法删除输出0
2.比赛中的思考
没想到什么比较正经的解法,直接暴力去做的
3.解题思路
根据模拟样例,可以发现公式,直接带入计算一下就行了
4.AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
int n;
int q;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	scanf("%d",&q);
	while(q--){
		int x;
		scanf("%d",&x);
		int ans=0;
		int flag=0;
		for(int i=n;i>=1;i--){
			if(a[i]<x){
				ans+=(x-a[i])/i;
				x=a[i]+(x-a[i])%i;
				if(x>a[i]){
					x-=i;
					ans++;
				}
			}
			if(a[i]==x){
				ans++;
				flag=1;
				break;
			}
		}
		if(flag){
			printf("%d\n",ans);
		}
		else{
			printf("0\n");
		}
	}
	return 0;
}

T4【平分糖果(candy)】:
1.题目大意
已知美味程度为i的糖果有a[i]个,问能不能把糖果平分成美味程度之和相同的两部分
2.比赛中的思考
没思路,写的偏分代码
3.解题思路
用dp[i][j]表示前i种物品,能否凑出价值j来,根据这个推出公式,计算就可以了
4.AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1.2e5+5;
int mark;
int a[10];
bool f[N];
int main(){
	while(~scanf("%d%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6])){
		int m=a[1]+a[2]*2+a[3]*3+a[4]*4+a[5]*5+a[6]*6;
		if(!m){
			break;
		}
		else{
			for(int i=1;i<=m;i++){
				f[i]=0;
			}
		}
		printf("Collection #%d:\n",++mark);
		f[0]=1;
		for(int i=1;i<=6;i++){
			for(int k=1;k<=a[i];k<<=1){
				for(int j=m;j>=i*k;j--){
					f[j]=f[j]|f[j-i*k];
				}
				a[i]-=k;
			}
			if(a[i]){
				for(int j=m;j>=i*a[i];j--){
					f[j]=f[j]|f[j-i*a[i]];
				}
			}
		}
		if(!(m&1)&&f[m>>1]){
			printf("Can be divided.\n");
		}
		else{
			printf("Can't be divided.\n");
		}
		printf("\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值