• 【t005】数字构造问题


    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;
    }
    
  • 相关阅读:
    表格边框的合并
    solr服务搭建
    JedisClient操作redis 单机版和集群版
    redis集群的搭建
    FastDfs的搭建
    打开与关闭端口
    zookeper分布式搭建1
    zookeper分布式搭建
    Zookeeper的安装
    Linux下Jdk的安装
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626669.html
Copyright © 2020-2023  润新知