CSP-X模拟赛一王胤皓补题报告

日期:2023.10.1                考试时间:9:30---->11:30

学号:S07738                    姓名:王胤皓

一、我的题目分数(有点尴尬)

T1爬楼梯(stair):(Wrong Answer)0分

T2字符折线图(sline):(Wrong Answer)50分

T3吉利数(lucknum):(Wrong Answer)40分

T4路灯照明(lighting):(Wrong Answer)30分

二、考试过程:

第一道题:

第一道题爬楼梯我理解错题意了。。。但是只需要给一个变量改一下就对了。(服了)

第二道题:

第二道题字符折线图,这一个题是我考试花费时间最多的一题。我思考了特别久,我测试了许多样例,都对了,但是最后只得了50分

第三题:

我只会求出80%的数据,就是用O(10^{5})的时间从1遍历到10^{5},用数组存不含有4的数字,后边多组测试数据,输入里面的数据,就可以用O(1)时间直接输出a_{n};

第四题:

我实在没有什么思路,只能用打暴力的方法偷分,就是用O(a*b*c*d),得了30分。

做题思路:

第一道题爬楼梯:

题目简单概括:

小可和达达从第一层出发,每次爬楼梯到达一个平台,就需要转身再爬到达两个平台代表上了一层楼。如果小可到了第八层,然后又向上爬了若干台阶,但是没有到第九层,那么输出第八层

思路:

第一步、输入n、x,作用同题目。

第二步、定义ans表示上了几个平台,cnt表示在这一个平台到下一个平台已经爬了的台阶数,在输入a数组的时候,用cnt加上当前走的步数,如果大于等于了每两个平台之间的台阶的数量,就说明又上了一个平台,因为在迈步子的时候,如果迈出去的台阶之后已经到了平台,那么无论能迈多少步,他都只是到了那个平台了,所以ans+1。

3、他问的是第几层所以是\left \lfloor ans/2 \right \rfloor他一开始是第一层,所以是1+\left \lfloor ans/2 \right \rfloor

旧代码(Wrong Answer【0分】)(因为理解错了):

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main(){
	int n,x;
	cin>>n>>x;
	int linux=x/2;
	int a[100005];
	int ans=1,cnt=0,sum=0;
	for(int i=1; i<=n; i++){
		cin>>a[i];
		cnt+=a[i];
		if(cnt>=linux){
			cnt=0;
			sum++;
		}
		linux=x-linux;
	}
	cout<

新代码(Accept【100,满分】):

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main(){
	int n,x;
	cin>>n>>x;
	int a[100005];
	int cnt=0,sum=0;
	for(int i=1; i<=n; i++){
		cin>>a[i];
		cnt+=a[i];
		if(cnt>=x){
			cnt=0;
			sum++;
		}
	}
	cout<

第二题字符折线图:

题目简单概括:

可以画出一个折线图。从第二个字符开始,如果它比它的上一个字符大,那么就是上升的,画一个   /   ;如果和上一个字符相同,那么画一个 -;如果比比上一个字符小,那么就是下降的,画一个    。并且上升的时候,要向上一行,下降的时候向下一行。

空白处使用空格填充,不要输出多余的空格。

思路:

1、输入字符串

2、画图详解:

CSP-X模拟赛一王胤皓补题报告_第1张图片

根据图片

先定义一个height(高度)=100和一个char类型二维数组,并全部赋值为空格

从第2个字符开始遍历字符串,

设当前字符在这个字符串中的位置为i

我们进行分类讨论

如果位置为i的字符的ASCLL值大于位置为i-1的字符的ASCLL码值
如果上一个是'/'

height减1,存储

如果上一个是'-'

height减1,存储

如果上一个是'\'

height不变,存储

如果位置为i的字符的ASCLL值小于位置为i-1的字符的ASCLL码值
如果上一个是'\'

height+1,存储

如果上一个是'-'

height+1,存储

如果上一个是'/'

height不变,存储

如果位置为i的字符的ASCLL值等于位置为i-1的字符的ASCLL码值
如果上一个是'/'

height减1,存储

如果上一个是'-'

height不变,存储

如果上一个是'\'

height+1,存储

(在求的时候,顺便求一下最高和最低)

3、打印矩阵。(tips:需要从最低开始,到最高结束,然后从后面进行遍历,如果检测到了不是空格的字符,那么记下来,然后for循环到记下来的数字,输出)

旧代码(Wrong answer(50分))

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main(){
    int flag[105];
    string a;
    cin>>a;
    int len=a.size();
    char cc;
    cc=a[0];
    for(int i=1;icc) flag[i]=0;
    	else flag[i]=2;
    	cc=a[i];
	}
	int height[105]={0};
	int heightcnt=100;
	for(int i=1; i=1; j--){
				height[j]++;
			}
		}
		if(flag[i]==2){
		    height[i]=heightcnt;
			heightcnt++;
		}
		else{
			height[i]=heightcnt;
		}
	}
	int begin=0,end=100,flag1=0;
	char c[300][300]={' '};
	for(int i=0;i<200; i++){
		int flagg=0;
		for(int j=1; j

新代码(Accept【100,满分】)

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main(){
    string a;
    cin>>a;
    int len=a.size();
    char c[222][222];
    memset(c,' ',sizeof c);
    int hhh=100,maxx=0,minn=400;
    for(int i=1; ia[i-1]){
    		if(c[hhh][i-1]!='\\'){
    			hhh--;
			}
			c[hhh][i]='/';
		}
		if(a[i]0; j--){
		    if(c[i][j]!=' '){
		    	len2=j;
		    	break;
			}
		}
		for(int j=1;j<=len2; j++){
			cout<

第三题吉利数:

题目简单描述:

小可认为一个数字中如果有4这个数字就是不吉利的。相对的,其他的数字就是吉利的。吉利的数字有1,2,3,5,6,7,8,9,10,..

小可想知道,第n个吉利的数字是多少。

思路:

将十进制转换为九进制,对于数字中大于等于4的位置加一输出即可。

因为相当于在十进制中,去掉了4这个数字,那么就是九进制。

旧代码(Wrong Answer(40分)):

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int a[5000005];
int main(){
	long long ans=0;
    for(int i=1; i<=5000009; i++){
    	ans++;
    	while(ans%10==4||ans/10%10==4||ans/100%10==4||ans/1000%10==4||ans/10000%10==4||ans/100000%10==4){
    		ans++;
		}
		a[i]=ans;
	}
	long long t;
    scanf("%lld",&t);
	while(t--){
		long long n;
		scanf("%lld",&n);
		if(n>=5000009){
			cout<<58737318092550<

新代码(Accept【100,满分】):

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main(){
	long long t;
	scanf("%lld",&t);
	while(t--){
		long long n;
		scanf("%lld",&n);
		stack sa;
		while(n){
			int temp=n%9;
			n/=9;
			if(temp>=4){
				temp++;
			}
			sa.push(temp);
		}
		while(sa.empty()!=1){
			printf("%d",sa.top());
			sa.pop();
		}
		printf("\n");
	}
	return 0;
}

第四题路灯照明 :

题目简单描述:

给定一个 2∗2 的网格,每个网格都有一盏路灯,且都在格点上,即:四盏路灯的位置分别是左上角, 右上角,左下角,右下角。

路灯都是需要耗电的,且耗电量与亮度有关,如果一盏路灯的耗电量是 x ,则它可以为他所在的格子提供 x 的亮度,并且为他相邻的格子提供 \left \lfloor \frac{n}{2} \right \rfloor,为他对角的格子提供\left \lfloor \frac{n}{4} \right \rfloor的亮度,其中 \left \lfloor n \right \rfloor表示对 x 向下取整。

某一个格子的亮度为四盏路灯为他提供的亮度之和,例如 左上角的灯耗电量为 4, 右上角的灯耗电量为 7,右下角的灯耗电量为 8,左下角的灯耗电量为 0,那么 左上角这个格子的亮度就是 4+ \lfloor \frac{7}{2} \rfloor + \lfloor \frac{7}{4} \rfloor+0 。

现在我们对四个格子的最低亮度提出了要求,我们想要让四个格子的亮度都达到标准。你可以将每一盏灯的耗电量调节为任何一个大于等于零的整数,为了省电, 你希望四盏灯的耗电量之和尽可能的小,请问四盏灯的最小耗电量之和是多小?

思路:

这段代码是比较难的,想到做法和思路超级难,并且运用的方法更让人出乎意料。这道题正确的做法是二分答案(最小化答案)算法+(超级优化版)枚举算法,非常让人出乎意料。

首先,我们要输如a、b、c、d。

然后,打上二分答案(最小化答案)的代码框架,接下来就要编写最最最难得地方,check()函数!

check函数里面:

要包含这些:

枚举左上亮度 

枚举右下

 a,d还有多少 

还有多少可以分配 

b还需要多少 

c还需要多少 

估算b的大概区间

b+c/4=bneed,b+c=now
b+c/4=bneed->得4b+c=4bneed
4b-c-4bneed -> 3b+now=4bneed
b=(4bneed-now)/4

枚举b在这个近似值附近在枚举 

左下提供+b>=b需要 左下>=c需要

每次只要check(mid,a,b,c,d)=true,就用一个变量ans=mid

最后输出ans即可

旧代码(Wrong Answer(30分)):

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main(){
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    int minn=0x3f3f3f3f;
    for(int i=0;i<=a;i++){
    	for(int j=0;j<=b; j++){
    		for(int k=0;k<=c; k++){
    			for(int t=0; t<=d; t++){
    				int ans1=i+(j/2)+(k/2)+(t/4);
    				int ans2=j+(i/2)+(k/4)+t/2;
    				int ans3=k+(i/2)+t/2+j/4;
    				int ans4=t+i/4+j/2+k/2;
    				if(ans1>=a&&ans2>=b&&ans3>=c&&ans4>=d){
    					if(minn>i+j+k+t){
    						minn=min(minn,i+j+k+t);
						}
					}
				}
			}
		}
	}
	cout<

新代码(Accept【100,满分】):

#include
#include
#include
#include
#include
#include
using namespace std;
bool check(int mid,int a,int b,int c,int d){
	for(int i=0;i<=a; i++){//枚举左上亮度 
		for(int j=0;j<=d; j++){//枚举右下 
			int need=max(a-i-j/4,d-j-i/4);//a,d还有多少 
			if((mid-i-j)/2得4b+c=4bneed
			//4b-c-4bneed -> 3b+now=4bneed
			//b=(4bneed-now)/4
			for(int k=max(0,bb-5);k<=min(now,bb+5);k++)//枚举b在这个近似值附近在枚举 
				if(k+(now-k)/4>=bneed&&k/4+now-k>=cneed)//左下提供+b>=b需要 左下>=c需要 
				    return true;
				    
		}
	}
	return false; 
}
int main(){
	int a,b,c,d;
	cin>>a>>b>>c>>d;
	int l=0,r=a+b+c+d,ans=a+b+c+d;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid,a,b,c,d)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	cout<

赛后总结

总结一:今天的题有点难

总结二:真正代码用的算法出乎意料

总结三:(专门写给某些人)考试的时候freopen和fclose记得写对,记得保存,记得保存的时候去掉注释着freopen和fclose的注释。

国庆节快乐

你可能感兴趣的:(C/C++,编程,算法,数据结构,c++,c语言,学习)