http://acm.hdu.edu.cn/showproblem.php?pid=1563
Find your present!
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2747 Accepted Submission(s): 1819
Each case will be presented by an integer n (1<=n<=200, and n is odd) at first. Following that, n positive integers will be given in a line. These numbers indicate the card numbers of the presents.n = 0 ends the input.
5 1 1 3 2 2 3 1 2 1 0
3 2
#include<stdio.h>
#include<string.h>
struct NUM
{
int N;
int num;
}num[400];
int main()
{
int M,i,j,k,a[400];
while(scanf("%d",&M)&&M!=0)
{
memset(a,0,sizeof(a));
for(i=0;i<M;i++)
scanf("%d",&a[i]);
for(i=0;i<400;i++)
num[i].num=0;
for(i=0,j=0;i<M;i++)
{
if(a[i]!=-1)
num[j].N=a[i];
else continue;
for(k=0;k<M;k++)
if(num[j].N==a[k])
{
num[j].num+=1;
a[k]=-1;
}
j+=1;
}
for(i=0;i<j;i++)
if(num[i].num==1)
break;
printf("%d\n",num[i].N);
}
return 0;
}
这道题就是让找只出现一次的那个号码,可以用数组,把号码存到数组中,然后扫描数组,把出现的号码和号码的个数放到结构体中,结构体是号码和号码出现的次数,然后输出号码出现次数是1对应的那个号码。
http://acm.hdu.edu.cn/showproblem.php?pid=2095
find your present (2)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/1024 K (Java/Others)
Total Submission(s): 15707 Accepted Submission(s): 5992
Each case will be presented by an integer n (1<=n<1000000, and n is odd) at first. Following that, n positive integers will be given in a line, all integers will smaller than 2^31. These numbers indicate the card numbers of the presents.n = 0 ends the input.
5 1 1 3 2 2 3 1 2 1 0
3 2use scanf to avoid Time Limit ExceededHintHint
#include<stdio.h>
#include<string.h>
int main()
{
int N,n,i,sum;
while(scanf("%d",&N)&&N!=0)
{
for(i=0,sum=0;i<N;i++)
{
scanf("%d",&n);
sum^=n;
}
printf("%d\n",sum);
}
return 0;
}
这道题是上道题的拓展,这道题的范围是1<=n<1000000,每个数不超过2^31,这说明测试数据会很大,我用上一题的做法提交,结果超内存。看其他人做才知道要用异或运输,异或运算是计算机中特有的,先把两个数转化成二进制码,然后异取1,同取0,如3^2=11^10=01,所以两个相同的数异或是0,2^2=10^10=00。因为这题输入的号码是偶数个,你的号码是出现一次的,剩余就是偶数个号码,而且其余的号码出现的次数也是偶数次(隐含条件,如果不是的话,就不能用异或运算),所以对号码依次进行异或运算,最后的号码就是出现1次的号码,即你的号码。
注意:
1)第一题用普通法(11855420)和异或法(11858741)如下图,可见在数据少的时候异或运算和普通运算一样。
第二题用普通法和异或法如下图,由此就可看出异或运输的优势,用普通法要用数组存,会超内存,而用异或运算不用储存。这也说明异或用算不会节省时间。
2)从这两道题还可以知道,这两道题还有一个隐含条件,即除了你的号码出现次数是1,其余号码出现次数都是偶数次。