Mac and Sequence | ||||||
| ||||||
Description | ||||||
Mac最近迷上了数列…现在他有一串由n个数组成的数列a1, a2, ..., an. 并且,Mac还写了个函数f(x) , 函数的功能定义如下: · f(0) = 0 · f(2·X) = f(X) · f(2·X+1) = f(X) + 1 Mac想知道有多少对下标(i, j)(1 ≤ i < j ≤ n) 满足 f(ai) = f(aj). 帮助Mac计算一下吧。 | ||||||
Input | ||||||
多组测试数据,每组测试数据第一行输入一个整数n (1 ≤ n ≤ 100000). 第二行包括n个整数 a1, a2, ..., an (1 ≤ ai ≤ 10^9) | ||||||
Output | ||||||
每组测试数据输出一个整数表示满足要求的下标对数。 | ||||||
Sample Input | ||||||
3 1 2 4 3 5 3 1 | ||||||
Sample Output | ||||||
3 1 | ||||||
Hint | ||||||
结果可能很大,注意使用long long.. | ||||||
Author | ||||||
`Wind@hrbust |
思路:
1、很明显,1 2 4 8 16.................pow(2,n)的值是一样的,那么我们不妨在考虑问题的时候,带入二进制思想。
2、想了半天,并没有什么好的想法,不如暴力敲一波f【i】的值,观察F【i】的值不难发现,其值就是i的二进制表达式中1的个数。
3、那么问题就简单了,对于输入,维护一个val【i】表示值为i的ai个数即可。
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
long long int val[500];
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(val,0,sizeof(val));
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
int cnt=0;
while(x)
{
cnt+=x%2;
x/=2;
}
val[cnt]++;
}
long long int ans=0;
for(int i=1;i<=100;i++)
{
if(val[i]==0)continue;
val[i]--;
ans+=(val[i]+1)*(val[i])/2;
}
printf("%lld\n",ans);
}
}