Day2补题报告

姓名:徐浩轩,校区:和谐校区,考试时间: 2024 2024 2024 10 10 10 2 2 2 09 : 00 : 00 09:00:00 09:00:00- 12 : 30 : 00 12:30:00 12:30:00,学号: S 08503 S08503 S08503

CSP-J Day 2 2 2 模拟赛补题报告

前言

考了我们班第3

T1 chess: A c c e p e t e d   100 \color{green}Accepeted\space100 Accepeted 100
T2 BigWater: W r o n g _ a n s w e r   0 \color{red}Wrong\_answer\space0 Wrong_answer 0
T3 delnum: W r o n g _ a n s w e r   5 \color{red}Wrong\_answer\space5 Wrong_answer 5
T4 candy: A c c e p e t e d   100 \color{green}Accepeted\space100 Accepeted 100

T1

题面

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

思路

根据题目描述暴力模拟即可,注意开long long(1.8*1e10)。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
struct node{
	int id,x,y,z,code;
}a[100005];
bool cmp(node x,node y){
	if(x.code==y.code){
		return x.id<y.id;
	}
	return x.code>y.code;
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>a[i].z>>a[i].y>>a[i].x;
		a[i].y=a[i].y+a[i].z/3;
		a[i].z%=3;
		a[i].x=a[i].x+a[i].y/3;
		a[i].y%=3;
		a[i].code=18*a[i].x+3*a[i].y+a[i].z;
		a[i].id=i;
	}
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;++i){
		cout<<a[i].id<<" ";
	}
	return 0;
}

T2

题面

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

思路

因为每格最多走1次,最多转1次,且最后要回到原点,那么可以理解为在矩阵中找一个矩形,让他四边上数字之和最大即可。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1005;
int n,a[N][N],r[N][N],c[N][N];
int main(){
	cin>>n;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			cin>>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]);
		}
	}
	cout<<ans+100;
	return 0;
}

T3

题面

有一个集合,初始状态里面有数字 1、2、3、4、5、……、正无穷,你可以理解为很多正整数。
现在给你一个长度为 n 数组 a (1<=a[i]<=1e9),每次操作将当前集合中第 a[1]小、第 a[2]小、……、第 a[n]小的数同时移除。
现在有 q 次询问,每次询问包含一个整数 x,查询从初始状态到删除 x 需要操作多少次。若无法删除,输出 0。

思路

看看要删的数在数组中处于什么位置,不断删除以减少它前面的数的个数,知道他被删除为止,最后将所有次数累加就是答案

代码

#include<bits/stdc++.h>
using namespace std;
int n,q,a[100005],x;
int main(){
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>a[i];
	}
	cin>>q;
	while(q--){
		cin>>x;
		int ans=0,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){
			cout<<ans<<"\n";
		}
		else{
			cout<<"0\n";
		}
	}
	return 0;
}

T4

题面

小可的妈妈给了小可很多的糖果,已经糖果都有美味程度,美味程度用1~6的整数表示。
有一天达达来小可家做客,小可要把糖果分给达达,现在已知了美味程度为 i 的糖果有 a[i] 个,请问小可能不能把糖果平分成美味程度之和相同的两部分。

思路

多重背包,推出状态转移方程f[j] = f[j] | f[j-i*k];看看f[sum/2]的值是否不为0即可

代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int mark,a[10];
bool f[N];
int main(){
    while(cin>>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");
        }
        cout<<"\n";
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值