整除15问题——北理工网教

题目如下:

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

测试用例


1
01431
103

测试用例输出


impossible
43110
30

分析:

首先,能被15整除的数肯定能被15的两个因数3和5整除,因此要求的最大值要满足两个条件:

1.最低位的数字是5或0

2.所有数位的数字之和是3的倍数

解决方法

因此,可以先计算所给数串的所有数字之和sum, 根据数字之和的不同可以分以下情况讨论:

  • sum % 3 == 0: 此时只需把所有的数字按照从大到小输出即可,输出时需注意:

    • 若0和5同时存在,或只有0,此时按照从大到小直接输出即可
    • 若只有5,则保留一位5,把剩余的数字从大到小输出,最后输出保留的5
  • sum % 3 == 1: 此时分两种情况:

    • 优先删除一位%3 == 1的数字(1,4,7),然后其余数字从大到小输出
    • 若没有%3 == 1 的数字,则删除两位%3 == 2的数字(2,5,8)
  • sum % 3 == 2:也分两种:

    • 优先删除一位%3 == 2的数字(2,5,8),其余数字从大到小输出
    • 若没有%3 == 2的数字,则删除两位%3 == 1的数字

需要特别注意:删除% 3 == 2的数字, 该数字是5的情况

Talk is Cheap, show me the code.

  1 /*************************************************************************
  2     > File Name: 15.cpp
  3     > Author: Max
  4     > Mail: I_am_M4x@protonmail.com
  5     > Created Time: 2017年03月29日 星期二 11时16分53秒
  6  ************************************************************************/
  7 #include <iostream>
  8 #include <string>
  9 #include <cstring>
 10 #include <algorithm>
 11 using namespace std;
 12 
 13 int cnt[10];
 14 int o[] = {1, 4, 7}, t[] = {2, 5, 8};
 15 long long int sum;
 16 int one, two;
 17 string num;
 18 
 19 void print()
 20 {
 21     bool flag = 0;
 22 
 23     for(int i = 9; i > 0; i--)
 24         if(cnt[i])
 25         {
 26             flag = 1;
 27             break;
 28         }
 29 
 30     if(!flag)
 31     {
 32         cout<<0<<endl;
 33         return;
 34     }
 35 
 36     flag = 0;
 37     if(!cnt[0])
 38     {
 39         cnt[5]--;
 40         flag = 1;
 41     }
 42 
 43     for(int i = 9; i >= 0; i--)
 44     {
 45         int j = 0;
 46         while(j++ < cnt[i])
 47             cout<<i;
 48     }
 49 
 50 
 51     if(flag)
 52         cout<<5;
 53 
 54     cout<<endl;
 55 }
 56 
 57 int main()
 58 {
 59     while(cin>>num)
 60     {
 61 
 62         memset(cnt, 0, sizeof(cnt));
 63         sum = 0;
 64         one = two = 0;
 65 
 66         for(int i = 0; i < num.length(); i++)
 67         {
 68             int n = num.at(i) - '0';
 69 
 70             if(n % 3 == 1)
 71                 one++;
 72 
 73             if(n % 3 == 2)
 74                 two++;
 75 
 76             sum += n;
 77             cnt[n]++;
 78         }
 79 
 80         if(! (cnt[5] || cnt[0]))
 81         {
 82             cout<<"impossible"<<endl;
 83             continue;
 84         }
 85 
 86         switch(sum % 3)
 87         {
 88             case 0:
 89                 {
 90                     print();
 91                     break;
 92                 }
 93 
 94             case 1:
 95                 {
 96                     if(!one)
 97                     {
 98                         if(two < 2)
 99                             cout<<"impossible"<<endl;
100 
101                         else
102                         {
103                             int del = 0;
104                             for(int k = 0; k < 3 && del < 2; k++ )
105                             {
106                                 while(cnt[t[k]] && del < 2)
107                                 {
108                                     if(t[k] == 5 && cnt[5] == 1 && cnt[8] && !cnt[5])
109                                             break;
110 
111                                     cnt[t[k]]--;
112                                     del++;
113                                 }
114                             }
115 
116                             print();
117                         }
118                     }
119 
120                     else
121                     {
122                         int del = 0;
123                         for(int k = 0; k < 3 && del < 1; k++)
124                         {
125                             while(cnt[o[k]] && del < 1)
126                             {
127                                 cnt[o[k]]--;
128                                 del++;
129                             }
130                         }
131 
132                         print();
133                     }
134 
135                     break;
136                 }
137 
138             case 2:
139                 {
140                     if(!two || (two == 1 && cnt[5] == 1))
141                     {
142                         if(one < 2)
143                             cout<<"impossible"<<endl;
144 
145                         else
146                         {
147                             int del = 0;
148                             for(int k = 0; k < 3 && del <2; k++)
149                             {
150                                 while(cnt[o[k]] && del < 2)
151                                 {
152                                     cnt[o[k]]--;
153                                     del++;
154                                 }
155                             }
156 
157                             print();
158                         }
159                     }
160 
161                     else
162                     {
163                         int del = 0;
164                         for(int k = 0; k < 3 && del < 1; k++)
165                         {
166                             while(cnt[t[k]] && del < 1)
167                             {
168 
169                                 if(t[k] == 5 && cnt[5] == 1 && cnt[8] && !cnt[0])
170                                         break;
171 
172                                 cnt[t[k]]--;
173                                 del++;
174                             }
175                         }
176                         print();
177                     }
178 
179                     break;
180                 }
181         }
182     }
183 
184     return 0;
185 }

这段代码在逻辑上有重叠的地方,Wa了一下午之后思维有点混乱= =

 提供几组比较特殊的测试用例:

5888 
550   
010  
58888 
1111115
2225
1222225
50000      
对应输出为:
885
0
0
885
11115
225
222225
0
posted @ 2017-03-30 08:32  M4x  阅读(896)  评论(0编辑  收藏  举报