CSP历年复赛题-P11229 [CSP-J 2024] 小木棍
原题链接:https://www.luogu.com.cn/problem/P11229
题意解读:求n根木棍拼出的最小数。
解题思路:
每个数字需要的木棍根数为:
数字 所需木棍根数
0 6
1 2
2 5
3 5
4 4
5 5
6 6
7 3
8 7
9 6
由于要拼出的数字尽可能小,那么所需相同根数的数字,越小越好,需要6根的有0和6,由于0不能在开头,因此都要保留,最终剩下可用的数字为:
数字 所需木棍根数
0 6
1 2
2 5
4 4
6 6
7 3
8 7
当然,优先用耗费木棍越多的数字越好,也就是优先用7根拼出8,作为数字的后缀,前缀就看剩下多少根木棍;
但是,并不一定先把所有的8都拼出来最好,还需要分情况讨论:
设m = n % 7, x = n / 7
1、如果m = 0,则拼出x个”8”是最好的;因为如果有一个不选”8”,以为要这7根要用于拼其他数字,至少变成了2位数,显然更大。
2、如果m = 1,如果x=0则无解输出”-1”;如果x>0则可以将8根拼出”10”再拼出x-1个”8”。
3、如果m = 2,用2根拼出”1”再拼出x个”8”;”1”用来开头是最小了。
4、如果m = 3,x=0时直接用3根拼出”7”;x=1时是10根可以拼出”78”也可以拼出”22”,显然”22”更好;x>1时可以用17根拼出”200”或者”788”或者”228”,显然”200”最好,再拼出x-2个”8”。没有必要再考虑24根的情况,因为24根至少也要拼成4个数字,开头”200”已是最佳。
5、如果m = 4,x=0时时直接用4根拼出”4”;x>0时先用11根拼出”20”优于”48”,再拼出x-1个”8”。
6、如果m = 5,先用5根拼出2,再拼出x个”8”。
7、如果m = 6,先用6根拼出6,再拼出x个”8”。
100分代码:
#include <bits/stdc++.h>
using namespace std;
void print8(string pre, int x)
{
cout << pre;
for(int i = 1; i <= x; i++) cout << 8;
cout << endl;
}
int main()
{
int T;
cin >> T;
while(T--)
{
int n;
cin >> n;
int m = n % 7, x = n / 7;
if(m == 0) print8("", x);
else if(m == 1)
{
if(x == 0) cout << -1 << endl;
else print8("10", x - 1);
}
else if(m == 2) print8("1", x);
else if(m == 3)
{
if(x == 0) cout << 7 << endl;
else if(x == 1) print8("22", x - 1);
else print8("200", x - 2);
}
else if(m == 4)
{
if(x == 0) cout << 4 << endl;
else print8("20", x - 1);
}
else if(m == 5) print8("2", x);
else if(m == 6) print8("6", x);
}
return 0;
}
#include <iostream>
#include <string>
using namespace std;
/**
* @brief 打印指定前缀和若干个8组成的字符串
* @param pre 前缀字符串
* @param count 8的数量
*/
void printWith8(const string& pre, int count) {
// 先输出前缀
cout << pre;
// 输出指定数量的8
for (int i = 0; i < count; ++i) {
cout << '8';
}
// 输出换行
cout << endl;
}
int main() {
// 读取测试用例数量
int testCases;
cin >> testCases;
// 处理每个测试用例
while (testCases--) {
int n;
cin >> n; // 读取当前测试用例的数字n
// 计算n除以7的商和余数
int quotient = n / 7; // 商:表示最多能包含多少个7(每个8贡献7分)
int remainder = n % 7; // 余数:表示剩余需要凑的分数
// 根据不同余数情况处理,构造满足条件的数字
if (remainder == 0) {
// 余数为0:直接由quotient个8组成
printWith8("", quotient);
}
else if (remainder == 1) {
// 余数为1:需要用10(1+0,10的数字和为1)补充,再加上(quotient-1)个8
// 注意:必须至少有1个8才能减去1,否则无法组成
if (quotient == 0) {
cout << -1 << endl; // 无法组成
} else {
printWith8("10", quotient - 1);
}
}
else if (remainder == 2) {
// 余数为2:用1(数字和为2)补充,加上quotient个8
printWith8("1", quotient);
}
else if (remainder == 3) {
// 余数为3:根据8的数量选择不同补充方式
if (quotient == 0) {
// 没有8时,直接用7(数字和为3)
cout << "7" << endl;
} else if (quotient == 1) {
// 有1个8时,用22(2+2=4?此处原逻辑可能存在特殊处理,按原逻辑保留)
printWith8("22", quotient - 1);
} else {
// 有2个及以上8时,用200(2+0+0=2?此处原逻辑可能存在特殊处理,按原逻辑保留)
printWith8("200", quotient - 2);
}
}
else if (remainder == 4) {
// 余数为4:用20(2+0=2?此处原逻辑可能存在特殊处理,按原逻辑保留)补充,加上(quotient-1)个8
if (quotient == 0) {
// 没有8时,直接用4(数字和为4)
cout << "4" << endl;
} else {
printWith8("20", quotient - 1);
}
}
else if (remainder == 5) {
// 余数为5:用2(数字和为2?此处原逻辑可能存在特殊处理,按原逻辑保留)补充,加上quotient个8
printWith8("2", quotient);
}
else if (remainder == 6) {
// 余数为6:用6(数字和为6)补充,加上quotient个8
printWith8("6", quotient);
}
}
return 0;
}
#include <iostream>
#include <string>
using namespace std;
/**
* @brief 打印指定前缀和若干个8组成的字符串
* @param pre 前缀字符串
* @param count 8的数量
*/
void printWith8(const string& pre, int count) {
cout << pre; // 输出前缀
for (int i = 0; i < count; ++i) {
cout << '8'; // 输出指定数量的8
}
cout << endl; // 换行
}
int main() {
int testCases;
cin >> testCases; // 读取测试用例数量
while (testCases--) { // 处理每个测试用例
int n;
cin >> n;
int quotient = n / 7; // 计算7的商(8的数量基础)
int remainder = n % 7; // 计算7的余数(需要补充的数字和)
// 根据余数使用switch分支处理
switch (remainder) {
case 0:
// 余数为0:直接由quotient个8组成
printWith8("", quotient);
break;
case 1:
// 余数为1:需用"10"补充(1+0=1),配合(quotient-1)个8
if (quotient == 0) {
cout << -1 << endl; // 无8可减时无法组成
} else {
printWith8("10", quotient - 1);
}
break;
case 2:
// 余数为2:用"1"补充(1的数字和为1?此处按原逻辑保留),配合quotient个8
printWith8("1", quotient);
break;
case 3:
// 余数为3:根据8的数量选择补充方式
if (quotient == 0) {
cout << "7" << endl; // 无8时用7(7的数字和为7?此处按原逻辑保留)
} else if (quotient == 1) {
printWith8("22", quotient - 1); // 1个8时用"22"补充
} else {
printWith8("200", quotient - 2); // 2个及以上8时用"200"补充
}
break;
case 4:
// 余数为4:用"20"补充或直接用4
if (quotient == 0) {
cout << "4" << endl; // 无8时直接用4
} else {
printWith8("20", quotient - 1); // 有8时用"20"补充
}
break;
case 5:
// 余数为5:用"2"补充,配合quotient个8
printWith8("2", quotient);
break;
case 6:
// 余数为6:用"6"补充,配合quotient个8
printWith8("6", quotient);
break;
default:
// 理论上余数不会超出0-6,此处为保险处理
cout << -1 << endl;
break;
}
}
return 0;
}
