CSP-J2024解题报告(T3)

小木棍

时间限制:C/C++ 1000MS,其他 2000MS
内存限制:C/C++ 256MB,其他 512MB

描述

小 S 喜欢收集小木棍。在收集了 n 根长度相等的小木棍之后,他闲来无事,便用它们拼起了数字。用小木棍拼每种数字的方法如下图所示。

现在小 S 希望拼出一个整数,满足如下条件:

  • 拼出这个数恰好使用 n 根小木棍;
  • 拼出的数没有前导 0;
  • 在满足以上两个条件的前提下,这个数尽可能小。

小 S 想知道这个数是多少,可 n 很大,把木棍整理清楚就把小 S 折腾坏了,所以你需要帮他解决这个问题。如果不存在正整数满足以上条件,你需要输出 −1 进行报告。

输入描述

本题有多组测试数据。

输入的第一行包含一个正整数 T,表示数据组数。

接下来包含 T 组数据,每组数据的格式如下:

一行包含一个整数 n,表示木棍数。

输出描述

对于每组数据:输出一行,如果存在满足题意的正整数,输出这个数;否则输出 −1。

样例输入 1 

5
1
2
3
6
18

样例输出 1 

-1
1
7
6
208

提示

提示

【样例 1 解释】

  • 对于第一组测试数据,不存在任何一个正整数可以使用恰好一根小木棍摆出,故输出 −1。
  • 对于第四组测试数据,注意 0 并不是一个满足要求的方案。摆出 9、41 以及 111 都恰好需要 6 根小木棍,但它们不是摆出的数最小的方案。
  • 对于第五组测试数据,摆出 208 需要 5+6+7=18 根小木棍。可以证明摆出任何一个小于 208 的正整数需要的小木棍数都不是 18。注意尽管拼出 006 也需要 18 根小木棍,但因为这个数有前导零,因此并不是一个满足要求的方案。

【数据范围】

对于所有测试数据,保证:1≤T≤50,1≤n≤105。

测试点编号n≤特殊性质
120
250
3103A
4,5105A
6103B
7,8105B
9103
10105

特殊性质 A:保证 n 是 7 的倍数且 n≥100。

特殊性质 B:保证存在整数 k 使得 n=7k+1,且 n≥100。

找规律,注意七以内。

#include<bits/stdc++.h>
using namespace std;
int main(){
	freopen("sticks.in","r",stdin);
	freopen("sticks.out","w",stdout);
	long long t,n;
	cin>>t;
	while(t--){
		scanf("%lld",&n);
		if(n==1)cout<<-1;
		else if(n==2)cout<<1;
		else if(n==3)cout<<7;
		else if(n==4)cout<<4;
		else if(n==5)cout<<2;
		else if(n==6)cout<<6;
		else if(n==7)cout<<8;
		else if(n%7==0){
			for(int i=1;i<=n/7;i++)cout<<8;
			printf("\n");
		}else if(n%7==1){
				printf("10");
				n-=8;
			for(int i=1;i<=n/7;i++)cout<<8;
			printf("\n");
		}else if(n%7==2){
			printf("1");
			n-=2;
			for(int i=1;i<=n/7;i++)cout<<8;
			printf("\n");
		}else if(n%7==3){

			if(n>=17){
				printf("200");
				n-=17;
				for(int i=1;i<=n/7;i++)cout<<8;
			}else if(n==10){
				printf("22");
			}
		
			printf("\n");
		}else if(n%7==4){
			if(n>=11){
				printf("20");
				n-=11;
				for(int i=1;i<=n/7;i++)cout<<8;
			}
			printf("\n");
		}else if(n%7==5){
			printf("2");
			n-=5;
			for(int i=1;i<=n/7;i++)cout<<8;
			printf("\n");
		}else if(n%7==6){
			if(n>=13){
				printf("68");
				n-=13;
				for(int i=1;i<=n/7;i++)cout<<8;
				
			}
			printf("\n");
		}
		if(n<8)cout<<'\n';
	}
	return 0;
}

<think>好的,用户让我介绍一下CSP-J复赛真题中的队列考题。首先,我需要确定用户的需求是什么。CSP-J是面向青少年的计算机能力认证,复赛通常涉及算法数据结构,队列是其中常见的一个考点。用户可能正在准备这个考试,或者想了解这类题目的类型和解题思路。 首先,我应该回忆一下CSP-J历年的真题,尤其是复赛部分涉及队列的题目。比如,2021年的复赛真题中有一道“小熊的果篮”问题,这题就涉及队列的应用。此外,可能还有其他年份的题目,比如2019年或2020年是否也有类似的题目? 接下来,我需要整理这类题目的共同特点。队列通常用于处理先进先出的问题,比如排队、广度优先搜索(BFS)等。在CSP-J的题目中,队列的应用可能涉及到模拟过程,比如处理水果篮的取出顺序,或者类似的需要按顺序处理元素的问题。 然后,我需要具体分析一个例子,比如“小熊的果篮”这道题。题目大意是小熊有一个由n个水果组成的果篮,包括苹果和橘子,排成一排。每天,从左到右,每一段连续的同种水果的第一个会被取出,直到全部取完。要求输出每天取出的水果编号。这题的关键在于如何高效模拟每天取水果的过程,队列在这里可能被用来管理当前剩下的水果,或者记录待处理的段。 解题思路方面,可能需要维护多个队列,或者使用双指针来跟踪当前段的位置。例如,每次处理时,找到所有连续同种水果的段,取出每段的第一个,然后将剩余的部分重新组织。这个过程可能需要多次迭代,直到所有水果被取完。这里队列可以帮助按顺序处理这些段,尤其是在处理动态变化的剩余水果时,队列的结构能够有效管理这些信息。 此外,还需要考虑时间复杂度的优化,因为直接模拟每一天的过程可能会导致超时,尤其是当数据量较大时。例如,使用队列来记录当前有效的段,每次处理时只遍历这些段,而不是整个数组,这样可以减少不必要的重复检查。 另一个可能的队列题目是类似于“约瑟夫环”的问题,或者需要处理排队中的某些规则,比如优先级的调整。但在CSP-J中,可能更倾向于基础的队列应用,如BFS或模拟过程。 总结来说,队列在CSP-J复赛真题中的应用通常涉及模拟问题,需要考生熟练掌握队列的基本操作,并能够将其灵活运用到具体的问题情境中。解题时要注意时间效率,避免暴力模拟导致超时,合理设计数据结构算法流程是关键。</think>CSP-J复赛中的队列相关考题通常考察对队列数据结构的理解及实际问题建模能力。以下以2021年CSP-J复赛真题**T3:小熊的果篮**为例进行解析: --- ### **题目概述** 小熊的果篮有`n`个水果(苹果/桔子),排列成一行。每天会进行以下操作: 1. 将当前所有**连续同种类水果段**的**第一个**水果取出 2. 重复操作直到果篮为空 要求输出每天被取出的水果编号序列。 --- ### **输入输出示例** **输入:** ``` 8 1 0 1 1 0 0 1 1 ``` **输出:** ``` 1 3 5 2 7 4 6 8 5 8 6 7 ``` --- ### **核心解题思路** 1. **队列维护有效区间** - 使用结构体记录每个连续段的`[左边界, 右边界, 水果类型]` - 用队列存储当前有效的连续段 2. **双指针预处理** 先遍历数组,预处理出所有初始的连续段: ```cpp struct Block { int l, r, type; }; queue<Block> q; // 预处理示例 for(int i=1; i<=n; ){ int j = i; while(j<=n && a[j]==a[i]) j++; q.push({i, j-1, a[i]}); i = j; } ``` 3. **模拟每日操作** - 记录当天要删除的位置 - 合并删除后产生的新连续段 ```cpp vector<int> today; // 记录当天要删除的编号 queue<Block> newQ; // 新队列 while(!q.empty()){ Block cur = q.front(); q.pop(); // 取出当前段的第一个元素 today.push_back(cur.l); cur.l++; // 如果段仍有剩余,放入待处理队列 if(cur.l <= cur.r) tmpQ.push(cur); } ``` 4. **合并相邻同类型段** 扫描临时队列,合并相邻的同类段: ```cpp while(!tmpQ.empty()){ Block cur = tmpQ.front(); tmpQ.pop(); // 合并相邻同类型段 if(!newQ.empty() && newQ.back().type == cur.type){ Block last = newQ.back(); newQ.pop(); newQ.push({last.l, cur.r, cur.type}); }else{ newQ.push(cur); } } ``` --- ### **时间复杂度优化** - **O(n)时间复杂度**:每个水果最多入队出队两次(初始预处理 + 合并操作) - **避免暴力模拟**:直接遍历数组模拟会达到O()复杂度,无法通过全部测试点 --- ### **关键考点** 1. **队列的灵活应用**:通过队列维护动态变化的连续段 2. **合并相邻区间的处理**:保证后续操作的正确性 3. **输出格式控制**:注意每天输出的空格与换行 --- ### **练习建议** 1. 完成[洛谷P7910](https://www.luogu.com.cn/problem/P7910)官方数据 2. 尝试其他队列经典问题: - 约瑟夫环问题(循环队列) - 滑动窗口最大值(双端队列) - 广度优先搜索(BFS)基础应用 建议在编写代码时注意边界条件处理,使用`STL queue`或手写队列均可,但要注意避免数组越界。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值