zl程序教程

您现在的位置是:首页 >  其它

当前栏目

【t005】数字构造问题

数字 构造 问题
2023-09-14 09:03:48 时间

Time Limit: 1 second
Memory Limit: 50 MB

【问题描述】

给定一个只包含数字[0..9]的字符串,请使用字符串中的某些字符,构建一个能够整除15最大的整数。注意,字符串中的每个字符只能使用一次。 任务:求由给定字符串构造的能够整除15的最大整数

【输入】

共1行;
输入数据为一个只包含数字[0..9]字符串,字符串的长度为1..1000。如果无法构建出该数字,请输出“impossible”。 

【输出】

输出一行数字串,表示能够整除15的最大整数。

【输入样例】

02041

【输出样例1】

4200

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=t005

【题解】

/*
    一个数字能被15整除;
    则这个数的各个位上的数字的和是3的倍数;
    末尾数字是0或5.
    把所有的数字从大到小排序;
    所有数字的和模3的结果;
    1.如果为0
        如果数字里面有0,则排序后0在最后面,则直接输出;
        如果数字里面没有0,但是有5,则把1个5放在最后面;然后输出;
        else
            put("Impossible");
    2.如果为1
        则如果有余数为1的数字,选那个最小的,删掉它;
        如果没有余数为1的数字,找两个余数为2的数字;
        {
            如果有0,则直接找两个最小的,删掉
            如果没有0,则要考虑
            是不是减掉一个5之后,还能找到两个余数为2的数字;
                能则删掉;
        }
        是否删掉了数字使得所有数字的和%3==0?
        是则根据有没有5和0,输出相应的答案;
        否则无解;
    2.如果为2
        则如果有1个余数为2的数字;
        {
            如果有0,则直接找最小的那个删掉;
            如果没有0,则要考虑
            是不是减掉一个5之后,还能找到一个余数为2的数字;
                能则删掉那个数字,否则"去找两个余数为1的数字",删掉;
        }
        没有
        则去找两个余数为1的数字;
            如果有就删掉最小的两个;
        是否删掉了数字使得所有数字的和%3==0?
        是则根据有没有5和0,输出相应的答案;
        否则无解;
*/


【完整代码】

#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 1000+100;

string s;
int bo[3];
int a[MAXN],n,num = 0,t5 = 0,t0 = 0;
bool ok1;

bool cmp(int x,int y)
{
    return x > y;
}

void find5()
{
    for (int i = 1;i <= n;i++)
        if (a[i]==5)
            {
                a[i]=-1;
                a[n+1] = 5;
                break;
            }
}

void output()
{
    int l = 1,r = n+1;
    while (a[l]==0 || a[l]==-1) l++;
    if (l>r)
        puts("0");
    for (int i = l;i <= n+1;i++)
        if (a[i]!=-1)
            printf("%d",a[i]);
}

void pd()
{
    if (ok1)//如果删掉数了
    {
        if (t0)//有0就直接输出
        {
            output();
            exit(0);
        }
        if (t5)//执行这一段就表示没0,则如果有5就把5移到最后输出
        {
            find5();
            output();
            exit(0);
        }
    }
    //没完成删数或没有0和5就输出无解
    puts("impossible");
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    cin >> s;
    n = s.size();
    for (int i = 0;i <= n-1;i++)
        {
            a[i+1] = s[i]-'0';
            bo[a[i+1]%3]++;
            num+=a[i+1];
            if (a[i+1]==5) t5++;
            if (a[i+1]==0) t0++;
        }
    sort(a+1,a+1+n,cmp);
    a[n+1] = -1;
    int x = num%3;
    if (x==0)
    {
        if (t0)
        {
            for (int i = 1;i <= n;i++)
                printf("%d",a[i]);
            return 0;
        }
        if (t5)
        {
            find5();
            for (int i = 1;i <= n+1;i++)
                if (a[i]!=-1)
                    printf("%d",a[i]);
            return 0;
        }
        puts("impossible");
        return 0;
    }
    if (x==1)
    {
        ok1 = false;
        if (bo[1])
        {
            for (int i = n;i >= 1;i--)
                if (a[i]%3==1)
                {
                    a[i] = -1;
                    break;
                }
            ok1 = true;
        }
        if (!ok1 && bo[2]>=2)
        {
            if (t0>0)//直接找两个余数为2的删掉(最小)
            {
                int cnt = 0;
                for (int i = n;i >= 1;i--)
                    if (a[i]%3==2)
                    {
                        cnt++;
                        a[i] = -1;
                        if (cnt==2)
                            break;
                    }
                ok1 = true;
            }
            //如果没有0,则还需要一个5
            //看一下删掉一个5(所以你得先有一个5)
            //之后还有没有两个余数为2的)->所以bo[2]>=3是条件
            if (!ok1 && t5 && bo[2]>=3)
            {
                //如果5只有一个,就不能选5
                bool ban5 = false;
                int cnt = 0;
                if (t5==1)
                    ban5 = true;
                for (int i = n;i>=1;i--)
                    if (a[i]%3==2)
                    {
                        if (ban5)
                            if (a[i]==5)
                                continue;
                        a[i] = -1;
                        cnt++;
                        if (cnt==2)
                            break;
                    }
                ok1 = true;
            }
        }
        //删数完成,根据0和5的个数判断输出
        pd();
    }
    if (x==2)
    {
        ok1 = false;
        if (bo[2])
        {
            if (t0)
            {
                for (int i = n;i>=1;i--)
                    if (a[i]%3==2)
                    {
                        a[i] = -1;
                        break;
                    }
                ok1 = true;
            }
            //如果下面这段执行是肯定没有0了
            //则肯定要有一个5,减去5会让bo[2]--,所以bo[2]要大于1
            if (!ok1 && t5 && bo[2]>1)
            {
                bool ban5 = false;
                if (t5==1)
                    ban5 = true;
                for (int i = n;i >= 1;i--)
                    if (a[i]%3==2)
                    {
                        if (ban5)
                            if (a[i]==5)
                                continue;
                        a[i] = -1;
                        break;
                    }
                ok1 = true;
            }
        }
        if (!ok1 && bo[1]>=2)
        {
            int cnt = 0;
            for (int i = n;i >= 1;i--)
                if (a[i]%3==1)
                {
                    a[i] = -1;
                    cnt++;
                    if (cnt==2)
                        break;
                }
            ok1 = true;
        }
        pd();
    }
    return 0;
}