整除15问题 题解

题目

给定一个只包含数字 [0…9] 的字符串,求使用字符串中的某些字符,构造一个能够被15整除的最大整数。注意,字符串中的每个字符最多只能使用一次。
输入:程序从标准输入读入数据,每行数据由一串数字组成,长度为1到1000。
输出:针对每一行输入,输出一个结果,每个结果占一行。如果无法构造出能够被15整除的整数,请输出impossible。
测试样例:
输入
1
01431
103
输出
impossible
43110
30

解题思路

首先,能被 15 15 15整除的数肯定能被 3 3 3 5 5 5 整除,所以个位数必须为 0 0 0 5 5 5

将读入的数字存入num[10]中,表示每一位数字出现几次,

nums[0]||nums[5]必须为true

再考虑被3整除,

如果一个数的各个位上数字之和能被3整除,那么这个数能被3整除

所以把各个位数相加得到sum ,考虑三种情况:

  • sum % 3 == 0

    那么这个数必然能被15整除(在考虑被3整除之前已经保证能被5整除了)

  • sum % 3 == 1

    必须删去1 , 4 , 7 中的一个数,优先较小者。如果不存在1,4,7, 则删除两次2,5,8

  • sum % 3 == 2

    必须删去2, 5 , 8 中的一个数,同样优先较小者,但在删除5的时候要注意保证数字05两者至少存在一个数,否则不能删除5,改为删除8。

    若不存在2,5,8 则删除两次1,4,7

特别注意:

0能被15整除!

代码

偏长,可能存在一些不必要的代码

#include <iostream>
using namespace std;

int nums[10];//存储每个数字出现几次
char s[1000];

void Init()//初始化,读入数据
{
    fill(nums,nums+10,0);
    int i = 0;
    while(s[i]!='\0')
    {
        if(s[i]>='0' && s[i]<='9')
        {
            nums[s[i]-'0']++;
        }
        i++;
    }
}
int Sum()
{
    int sum = 0;
    for(int i=0; i<10;i++)
    {
        sum+=i*nums[i];
    }
    return sum;
}
bool Del(int f,int &sum)//删除不被3整除情况下的一个数字
{
    if(f==1)
    {
        if(nums[1])
        {
            nums[1]--;
            sum-=1;
            return true;
        }
        else if(nums[4])
        {
            nums[4]--;
            sum-=4;
            return true;
        }
        else if(nums[7])
        {
            nums[7]--;
            sum-=7;
            return true;
        }
        else {
            return false;
        }
    }
    if(f==2)
    {
        if(nums[2])
        {
            nums[2]--;
            sum-=2;
            return true;
        }
        else if(nums[0]==0?nums[5]>1:nums[5])//保证至少有1个0或5
        {
            nums[5]--;
            sum-=5;
            return true;
        }
        else if(nums[8])
        {
            nums[8]--;
            sum-=8;
            return true;
        }
        else {
             return false;
        }
    }
    return false;
}
bool Div()//主函数 返回能否组成被15整除的数
{
    int sum = Sum();
    while(sum >= 0)
    {
        if(sum%3==0){
            if(nums[0]||nums[5]){
                if(sum == 0) nums[0]=1;//防止输出类似0000的结果
                return true;
            }
            return false;
        }
        else if(sum%3==1){
            if(!Del(1,sum))//删除一个数,删除失败则删除两个数
            {
                bool flag = Del(2,sum)&&Del(2,sum);
                if(flag) {
                    if(sum==0){
                        if(nums[0]>0) {nums[0]=1;}
                        else flag = false;
                    }
                }  
               return flag;
            }
        }
        else if(sum%3==2){
            if(!Del(2,sum))//同上
            {
                bool flag = Del(1,sum)&&Del(1,sum);
                if(flag) {
                    if(sum==0){
                        if(nums[0]>0) {nums[0]=1;}
                        else flag = false;
                    }
                }  
               return flag;
            }
        }
    }
    return false;
}

int main()
{
    while(scanf("%s",s)!= EOF)
    {
        Init();  
        if(Div()&&(nums[0]||nums[5]))//优先保证末尾是0或5,在没有0的情况下取出一个5放在末尾
        {
            if(nums[0]==0) nums[5]--;
            for(int i = 9; i >=0; i--)
            {
                for(int j = 0; j < nums[i]; j++)
                {
                    cout << (char)('0'+i);
                }
            }
            if(nums[0]==0) cout<<"5";
            cout << endl;
        }

        else cout<< "impossible"<<endl;
        fill(s,s+1000,0);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值