奇妙糖果屋
Time Limit : 3000/1000ms (Java/Other) MemoryLimit : 65535/32768K (Java/Other)
Total Submission(s) : 13 Accepted Submission(s) :11
Problem Description
奇异王国里有很多奇怪的事物。比如奇怪的人(每个人都拥有一个智慧值),奇怪的商店......
这不,奇异糖果屋今天开业了,老板在门口拉上了“糖果送送送”的横幅来吸引顾客。
糖果的具体赠送方案为对于一个智慧值为
x
的人来说,他所能获得的糖果数量
f
(
x
)
满足如下条件:
1
.
f
(
0
)
=
0
,
2
.
f
(
2
x
)
=
f
(
x
)
,
3
.
f
(
2
x
+1)
=
f
(
2
x
)
+
1
,
整天搞怪的小A带着朋友们闻讯而来,他想出了一个游戏,游戏的规则是这样的:每个人根据自己的智慧值拿到糖果后互相比较开心值,开心值最大的人即为胜者。
开心值的定义为除了自己以外其他所有人获得糖果数量的异或值。
但是小A只负责搞怪,目前已知每个人的智力值,聪明的你能否帮助他提前知道谁能获胜以及这个人的开心值为多少呢?
每个人按照给定顺序从
1
开始编号。如果有多个人的开心值相等,则编号最小的获胜。
Input
输入数据的第一行是一个整数
T
,表示测试实例的个数,保证
T
<=
100
。
每组输入数据占两行。
第一行为一个整数
n
,代表去糖果屋的人数。(
1<=n<=105
)
第二行为
n
个整数,代表每个人的智力值
a
i
。(
1<=ai<=109
)
题目保证
n
>=50000
的数据组数不超过
10
组。
Output
每组数据输出两个整数,依次表示获胜的人的编号以及他所获得的开心值,中间用空格隔开。
Sample Input
1
2
3 4
Sample Output
2 2
【题意】
略。
【思路】
我们对f(x)进行分析后,发现f(x)的值便是x的二进制表示中1的个数。那么我们只要调用__builtin_popcount()函数即可以快速求出每个人获得的糖果数。当然手动模拟也可以。
这里,我们在读入的时候顺便保存每个人获得糖果数的异或总和sum。根据异或的性质:a ^ b ^ b=a ,对于每个人我们只要用他所获得的糖果数异或sum便是他的开心值。
扫一遍保存最大值即可。
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)
typedef long long ll;
const int maxn = 100005;
const ll mod = 1e9+7;
const ll INF = 0x3f3f3f3f;
const double eps = 1e-9;
int a[maxn];
int main()
{
/*freopen("c://ccpc//problem 1001 data.txt","r",stdin);
freopen("c://ccpc//problem 1001 results.txt","w",stdout);*/
int n;
rush()
{
scanf("%d",&n);
int Max=-1;
int pos=0;
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]=__builtin_popcount(a[i]);
sum^=a[i];
}
for(int i=1;i<=n;i++)
{
if((sum^a[i])>Max)
{
Max=(sum^a[i]);
pos=i;
}
}
printf("%d %d\n",pos,Max);
}
return 0;
}