CSP-J复赛真题解析

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;
}