みねちゃんの修罗场
Time Limit: 5000 mSec Memory Limit: 1024 KB
Description
みねちゃん是个成绩优秀大学二年级学生,本来是和像自己妹妹一般的青梅竹马一起过着普通的大学生活的,但某天却被校内公认的第一美人表白了。然而她的真实意图却是为了骗过众人而需要みねちゃん与她假扮情侣。被掌握了自己的某个“秘密”的みねちゃん被迫假扮“男友”这一角色……然而在此之后他的“未婚妻”也加入了进来,围绕みねちゃん的壮烈修罗场就此拉开帷幕!(这个剧本怎么这么眼熟。。。)
又是一年的情人节,为了不误入柴刀END,みねちゃん必须要给三个“女友”送三份一模一样的礼物(开后宫的难度真是大啊~)。作为一个土豪,みねちゃん自然是买了好多好多的东西准备送给三个妹子,然而当买好的东西送到家时,みねちゃん一眼发现东西少了一件!みねちゃん在X东下了N份订单,每份订单包括一模一样的3件礼物,(有可能会多次购买同一种的礼物)结果只送了3*N-1件来。可惜的是,みねちゃん只能一眼看出礼物少了一件,并不能看出少的到底是哪一种,现在只好委托你根据每件物品的编号来检查一下,到底是哪一种少送了一件(数量不是3的倍数)。你问我为什么他不自己检查?拜托,人家可是有三个妹子的,怎么可能有那么多空闲时间,所以这种无聊的事情还是交给你好了~
Input
第一行一个整数N,即みねちゃん一共订购了N份礼物接下来3*N-1个数,表示送来的物品的物品编号。由于X东物品种类丰富,物品编号均为十位的十进制整数,可能会有前导零。编号间可能有换行。输入文件保证不大于64M。
Output
一个数,表示缺少的那件礼物的订单号。记得换行。
Sample Input
2
0000000001 0000000002 0000000002 0000000001 0000000002
Sample Output
0000000001
简易版本:
有一个数字出现1次,其他都出现两次,找出出现1次的数
解决方案:对所有数都异或一下。
算法原理:任何数异或0值不变,任何数与自己异或值为0。
思路一:
把每个数字拆成若干位,每位就开数组统计一下该位出现的次数,然后把取模3为2的几位拿出来在合并一下。
#include<iostream>
#include<cstdio>
using namespace std;
int pow(int x,int n)
{
int res = 1;
while (n>0)
{
if (n&1)
{
res = res*x;
}
x *= x;
n >>= 1;
}
return res;
}
int main()
{
int N;
while (~scanf("%d",&N))
{
int bitset[40] = {0};
int tmp,res = 0,cnt = 0;
for (int i = 0;i < 3*N-1;i++)
{
scanf("%d",&tmp);
cnt = 0;
while (tmp)
{
bitset[cnt++] += tmp%2;
tmp /= 2;
}
}
for (int i = 0;i < 33;i++)
{
if (bitset[i]%3==0)
{
bitset[i] = 0;
}
}
for (int i = 0;i < 33;i++)
{
if (bitset[i])
{
res += pow(2,i);
}
}
printf("%010d
",res);
}
return 0;
}
思路二:利用位运算(暂时没理清,位运算硬伤)
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int N;
while (scanf("%d",&N))
{
int a,a1,a2,a3;
a1 = a2 = 0;
for (int i =0;i < 3*N-1;i++)
{
scanf("%d",&a);
a2 |= a1&a; //更新出现两次的
a1 ^=a; //更新出现一次的,同时会抹掉第一位
a3 = ~(a1&a2); //找出没有出现的
a1 &= a3; //从第一位抹掉
a2 &= a3; //从第二位抹掉
}
printf("%010d
",a2);
}
return 0;
}