user-0 提问: oj的一个题目求解

回复:
user: user-0
content: 引用 5 楼 JiangWenjie2014 的回复:a)10^6个整数，每个数4字节，如果全部保存下来的话，1000KB内存是不够的。 b)而且数字的范围这么大，用bitset也不行，需要512MB内存。 所以不可能把数字保存下来，只能用scanf将数字过一遍，然后立即得到结果。 题目中说了，N-1个数出现3次，只有一个出现2次，刚开始觉得要用异或，但是题目条件刚刚不满足异或（要是N-1个数出现偶数次，另外一个出现奇数次，那直接异或就可以了）。果然题目不是这么解的。 之后，由于每个数都是32bit，我想有没有可能把每个数拆散（拆成4个byte，分别统计，然后再组合得到结果），因为一个byte的范围是0~255，数组长度256就可以统计了。比如一个数是0x12345678，出现了3次，那么最高位置对应的字节0x12也出现了三次，统计每个数最高位置字节值为0x12，出现的次数n，如果刚好那个出现两次的数最高位也包含0x12，那么n%3觉得等于2（就是不等于0），0x12不就拿出来了？其他三个字节也是这么得到。 就把一个大问题分成几个小问题然后解决。  多谢了。

user: user-1
content: a)10^6个整数，每个数4字节，如果全部保存下来的话，1000KB内存是不够的。 b)而且数字的范围这么大，用bitset也不行，需要512MB内存。 所以不可能把数字保存下来，只能用scanf将数字过一遍，然后立即得到结果。 题目中说了，N-1个数出现3次，只有一个出现2次，刚开始觉得要用异或，但是题目条件刚刚不满足异或（要是N-1个数出现偶数次，另外一个出现奇数次，那直接异或就可以了）。果然题目不是这么解的。 之后，由于每个数都是32bit，我想有没有可能把每个数拆散（拆成4个byte，分别统计，然后再组合得到结果），因为一个byte的范围是0~255，数组长度256就可以统计了。比如一个数是0x12345678，出现了3次，那么最高位置对应的字节0x12也出现了三次，统计每个数最高位置字节值为0x12，出现的次数n，如果刚好那个出现两次的数最高位也包含0x12，那么n%3觉得等于2（就是不等于0），0x12不就拿出来了？其他三个字节也是这么得到。 就把一个大问题分成几个小问题然后解决。

user: user-0
content: 引用 2 楼 JiangWenjie2014 的回复:思路：把32bit整数拆成4个8bit的数字分别统计，最后把4个8bit的数整合得到结果。  #include <stdio.h>  unsigned char get_byte0(int val) {     return val & 0xff; }  unsigned char get_byte1(int val) {     return (val >> 8) & 0xff; }  unsigned char get_byte2(int val) {     return (val >> 16) & 0xff; }  unsigned char get_byte3(int val) {     return (val >> 24) & 0xff; }  int get_int(int b0, int b1, int b2, int b3) {     return ((b0 & 0xff) <<  0) |            ((b1 & 0xff) <<  8) |            ((b2 & 0xff) << 16) |            ((b3 & 0xff) << 24); }  int find_byte(int arr[256]) {     int i;     for (i = 0; i < 256; ++i)     {         if (0 != arr[i] % 3)             return i;     }      printf("never reach here!\n");     return 0; }  int main (int argc, char *argv[]) {     int arr0[256] = {0};     int arr1[256] = {0};     int arr2[256] = {0};     int arr3[256] = {0};      int n;     scanf("%d", &n);      int i, t, sum = 3 * n - 1;     for (i = 0; i < sum; ++i)     {         scanf("%d", &t);         ++arr0[get_byte0(t)];         ++arr1[get_byte1(t)];         ++arr2[get_byte2(t)];         ++arr3[get_byte3(t)];     }      int b0, b1, b2, b3;      b0 = find_byte(arr0);     b1 = find_byte(arr1);     b2 = find_byte(arr2);     b3 = find_byte(arr3);      int ret = get_int(b0, b1, b2, b3);      printf("%d\n", ret);      return 0; }  想问问这个思路怎么想到的？

user: user-0
content: 引用 2 楼 JiangWenjie2014 的回复:思路：把32bit整数拆成4个8bit的数字分别统计，最后把4个8bit的数整合得到结果。  #include <stdio.h>  unsigned char get_byte0(int val) {     return val & 0xff; }  unsigned char get_byte1(int val) {     return (val >> 8) & 0xff; }  unsigned char get_byte2(int val) {     return (val >> 16) & 0xff; }  unsigned char get_byte3(int val) {     return (val >> 24) & 0xff; }  int get_int(int b0, int b1, int b2, int b3) {     return ((b0 & 0xff) <<  0) |            ((b1 & 0xff) <<  8) |            ((b2 & 0xff) << 16) |            ((b3 & 0xff) << 24); }  int find_byte(int arr[256]) {     int i;     for (i = 0; i < 256; ++i)     {         if (0 != arr[i] % 3)             return i;     }      printf("never reach here!\n");     return 0; }  int main (int argc, char *argv[]) {     int arr0[256] = {0};     int arr1[256] = {0};     int arr2[256] = {0};     int arr3[256] = {0};      int n;     scanf("%d", &n);      int i, t, sum = 3 * n - 1;     for (i = 0; i < sum; ++i)     {         scanf("%d", &t);         ++arr0[get_byte0(t)];         ++arr1[get_byte1(t)];         ++arr2[get_byte2(t)];         ++arr3[get_byte3(t)];     }      int b0, b1, b2, b3;      b0 = find_byte(arr0);     b1 = find_byte(arr1);     b2 = find_byte(arr2);     b3 = find_byte(arr3);      int ret = get_int(b0, b1, b2, b3);      printf("%d\n", ret);      return 0; }  多谢了，这个行。

user: user-1
content: 思路：把32bit整数拆成4个8bit的数字分别统计，最后把4个8bit的数整合得到结果。  #include <stdio.h>  unsigned char get_byte0(int val) {     return val & 0xff; }  unsigned char get_byte1(int val) {     return (val >> 8) & 0xff; }  unsigned char get_byte2(int val) {     return (val >> 16) & 0xff; }  unsigned char get_byte3(int val) {     return (val >> 24) & 0xff; }  int get_int(int b0, int b1, int b2, int b3) {     return ((b0 & 0xff) <<  0) |            ((b1 & 0xff) <<  8) |            ((b2 & 0xff) << 16) |            ((b3 & 0xff) << 24); }  int find_byte(int arr[256]) {     int i;     for (i = 0; i < 256; ++i)     {         if (0 != arr[i] % 3)             return i;     }      printf("never reach here!\n");     return 0; }  int main (int argc, char *argv[]) {     int arr0[256] = {0};     int arr1[256] = {0};     int arr2[256] = {0};     int arr3[256] = {0};      int n;     scanf("%d", &n);      int i, t, sum = 3 * n - 1;     for (i = 0; i < sum; ++i)     {         scanf("%d", &t);         ++arr0[get_byte0(t)];         ++arr1[get_byte1(t)];         ++arr2[get_byte2(t)];         ++arr3[get_byte3(t)];     }      int b0, b1, b2, b3;      b0 = find_byte(arr0);     b1 = find_byte(arr1);     b2 = find_byte(arr2);     b3 = find_byte(arr3);      int ret = get_int(b0, b1, b2, b3);      printf("%d\n", ret);      return 0; }

user: user-2
content: 题目提示,测试数据量巨大,常规方法肯定不行