题目描述
Given an array with N integers where all elements appear three times except for one. Find out the one which appears only once.
输入格式
Several test cases are given, terminated by EOF.
Each test case consists of two lines. The first line gives the length of array N(1≤N≤105), and the other line describes the Nelements. All elements are ranged in [0,263−1].
输出格式
Output the answer for each test case, one per line.
输入样例
4
1 1 1 3
10
1 2 3 1 2 3 1 2 3 4
输出样例
3
4
①C
主要思路是对所有数字进行异或运算, 模拟二进制加法,异或运算有a⊕b⊕a=b这样的性质, 所以可以设app_1, app_2代表出现一次和两次的数, 用not_three代表所有没有出现三次的数, 通过位运算, 最后app_2和出现三次的数被清0, 只剩下app_1, 也就是结果。
异或运算本质是二进制位运算,app_1保留出现奇数次的数,一旦出现两次就将进入app_2并从app_1中擦除,如果出现三次就会因为同时出现在app_1和app_2中而被not_three擦除,每次app_1和app_2都要和not_three进行一次与运算确保app_1和app_2中没有存放大于等于三次的数, 所以最终保留的app_1就是只出现一次的数。这个办法通过改变变量个数可以满足一切的查找唯一出现次数的问题,可设app[]进行保存。
---数学没学好真是太痛了
#include<stdio.h> main() { long long x, n, app_1, app_2, not_three; while(scanf("%lld",&n)!=EOF){ app_1=0, app_2=0; while(n--){ scanf("%lld",&x); app_2 |= app_1&x; app_1 ^= x; not_three = ~(app_1&app_2); app_1 = not_three&app_1; app_2 = not_three&app_2; } printf("%lld ",app_1); } return 0; }
或:
此类题目的描述多形如“在一堆正整数中,有一个数恰好出现了B次,而其他的数均出现了A次,一共有N个数,请求出那出现B次的数,数据保证有解”。
设题目输入为:
第一行3个正整数n,a,b( b<a ),第二行n个正整数,所有的数均在int范围之内。输出那个出现b次的数。
分析:
针对此类题目,我们在此给出一个通解——位统计法:本题中,所有数大小在int范围内,所以数字长度最长不超过10,我们开一个10*10的二维数组。用来统计,所有数字中出现在从第1位(个位)起到第10位(十亿位)每一位上0~9这10个数字每个数字出现的次数。
然后我们处理完之后,最后只需要从第10位(十亿位)开始到第1位(个位)依次检查0~9这10个数字出现的次数中,有没有不被a整除的即可,如果有,输出之,就可以得到你想要的那个出现了b次的数了。
1 #include<stdio.h> 2 #define clr(a) memset(a,0,sizeof a) 3 4 int main(){ 5 int i,j,cnt[20][20]={0},n; 6 while(scanf("%d",&n)!=EOF){ 7 clr(a); 8 getchar(); 9 for(i=0;i<n;i++){ 10 char ch; 11 j=0; 12 while((ch=getchar())>47) 13 cnt[j++][ch-48]++; 14 } 15 for(i=0;i<20;i++) 16 for(j=0;j<20;j++) 17 if(cnt[i][j]%3) 18 printf("%c",j+'0'); 19 printf(" "); 20 } 21 return 0; 22 }
②C++死活超时。。。PS:有两种思路。忘了回头补吧