题目链接:http://codeforces.com/problemset/problem/305/A
题目意思:给出一个序列,需要从中选择一些数,这些数需要满足:任意的两个数中每一位至少有一个数满足该位有0。例如,406, 10(可以看成010)是符合条件的; 406, 11 就不符合条件,因为个位上这两个数都不包含0。
一开始想得太过复杂:把整型的数保存到字符数组中,再用strstr函数找出是否有0的存在,但是这样做根本不能解决问题,因为不能得出0的具体位置。并且不能判断出两个数中的不同位至少有一个有0这个问题;后来甚至想到用位运算,看了下tutorial,原来又把问题想复杂了。
其实,解决的方法不难。首先看数据范围,最大是100,最小是0。这两个数肯定是要保存下来的,因为它和任何一个在区间(0, 100)中的数相加都符合每一位至少有一个数有0。接着考虑个位上的数,即(0,10),只需要保存一个,还有[10, 100)中被10整除的数,也是只需要保存一个。举个例子,比如8,30, 100, 0,两两组合都符合至少两个数中满足某一位是0的(不够位的,可以在前面添0,8可以看成008或者08)。至于[10, 100)中不能被10整除的数有一种情况也是需要只保存一个的,就是当序列中只有0或100或两个同时都有。
特别要注意一个比较容易遗忘的细节,很阴险的说~~~当序列中只有一个数的时候,无论是什么,都需要输出。隐含是满足条件的!!!卑鄙!!!
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 using namespace std; 5 6 const int maxn = 100 + 5; 7 int ans[maxn]; 8 9 int main() 10 { 11 int i, k, tmp, tmp1, cnt, cnt1, flag, flag1, flag2, flag3; 12 while (scanf("%d", &k) != EOF) 13 { 14 // freopen("in.txt", "r", stdin); 15 flag = flag1 = flag2 = flag3 = 0; 16 cnt1 = cnt= 0; 17 for (i = 0; i < k; i++) 18 { 19 scanf("%d", &tmp); 20 if ((tmp == 0 || tmp == 100) && cnt1 <= 2) // 0 or 100,cnt1不用也可以,只是为了严谨,防止序列中有多个重复的0或100 21 { 22 ans[cnt++] = tmp; 23 cnt1++; 24 flag = 1; 25 } 26 else if (tmp >= 10 && tmp < 100) // [10, 100) 27 { 28 if (tmp % 10 == 0 && !flag1) // 10的倍数 29 { 30 ans[cnt++] = tmp; 31 flag1 = 1; 32 } 33 else if (!flag2) // 不是10的倍数 34 { 35 tmp1 = tmp; // 暂时保留,因为有可能不需要输出 36 flag2 = 1; 37 } 38 } 39 else if (tmp > 0 && tmp < 10 && !flag3) // (0, 10) 40 { 41 ans[cnt++] = tmp; 42 flag3 = 1; 43 } 44 } 45 if (flag && !flag1 && !flag3 && k != 1) 46 { 47 if (flag2) // 这个条件十分关键 48 ans[cnt++] = tmp1; 49 } 50 if (flag2 && !flag && !flag1 && !flag3) 51 printf("1\n%d\n", tmp); 52 else 53 { 54 printf("%d\n", cnt); 55 for (i = 0; i < cnt; i++) 56 printf("%d ", ans[i]); 57 printf("\n"); 58 } 59 } 60 return 0; 61 }
来源:https://www.cnblogs.com/windysai/p/3383161.html