Sicily 4423. Calculate the Sum 解题报告

题目:

Constraints

Time Limit: 1 secs, Memory Limit: 256 MB

Description

Mike has recently been visited by extraterrestrials from planet X3, where everyone's name is a positive integer. All residents of the planet know each other. Two X3-ians calculate the strength of their friendship by converting their names to binary, aligning them one under the other, and writing a digit in each column: 0 if the two binary digits in that column are equal, 1 if they differ. The binary result is then converted back to the decimal system.

For example, the friendship value of 19 and 10 equals 25:

                      1 0 0 1 1 = 19

                      0 1 0 1 0 = 10

                      -----------------

                      1 1 0 0 1 = 25

 

The value of a planet in the Universe is defined as the sum of all friendship values. Mike has asked you to help him compute the value of planet X3.

Input

The first line contains an integer T (1<=T<=10)- indicating the number of test cases.

For each case, the first line contains a positive integer N (2<=N <=1000000), indicating the number of residents of planet X3. The next N lines contain the names of residents - positive integers smaller than 1000000, one per line.

Output

One line for each case, each line contains an integer - the value of planet X3. You should use long long instead of int for the large case.

Sample Input

2
3
7
3
5
5
9
13
1
9
6

Sample Output

12
84

这道题我一开始的思路是将name都存进数组中,然后全部化为二进制,再用2个for循环逐个人找与其他的的value并加起来,最后果然不出所料愉快的TLE了。

只好再网上找了一个优化的方案:对于所有的二进制数,不需要两两进行按位运算,只需要统计n个二级制数每个位共有多少个1,多少个0再简单运算即可。例如共有n个二进制数,其中第i位上共有k个1,n-k个0,然后结果只需要加上k*(n-k)*2^j次方即可(2^j次方为该位的权数)。由于最大数据1000000转化为二进制不会超过20位,所以只需要开一个20位的数组来存放各位上1的个数,而0的个数用人数-1的个数即可。由于数据量很多,用scanf会比用cin节省很多时间。

 1 #include<iostream>
 2 #include<math.h>
 3 using namespace std;
 4 
 5 
 6 int main(){
 7     int testCases;
 8     cin>>testCases;
 9     while(testCases--){
10         long long numOfResidents;
11         cin>>numOfResidents;
12         int countOfBinaryOne[20]={0};//数据全部的二进制数的某一位一共有多少个1
13         for(long long i=0;i<numOfResidents;i++){
14             long long name;
15             cin>>name;
16             int count=19;
17             while(name>0){//不断除以2用得到的余数组成它的二进制
18                 if(name%2==1){
19                     countOfBinaryOne[count]++;
20                 }
21                 count--;
22                 name/=2;
23             }
24         }
25         long long value=0;
26         for(int i=0;i<20;i++){
27             value+=countOfBinaryOne[i]*(numOfResidents-countOfBinaryOne[i])*pow(2,20-i-1);
28         }
29         cout<<value<<endl;
30     }
31     return 0;
32 }
原文地址:https://www.cnblogs.com/jolin123/p/3329869.html