题目描述
AK掉五校联考的题目后,鑫鑫在研究二进制在数论中的应用。
鑫鑫给了你n个数,每次你可以从这其中选择两个数a和b,将它们的值分别赋为a and b和a or b(均为二进制位运算)。这样的操作,你可以执行任意多次。鑫鑫希望最终这些数的平方和尽量的大,你能帮他求出这个最大值吗?
鑫鑫给了你n个数,每次你可以从这其中选择两个数a和b,将它们的值分别赋为a and b和a or b(均为二进制位运算)。这样的操作,你可以执行任意多次。鑫鑫希望最终这些数的平方和尽量的大,你能帮他求出这个最大值吗?
输入
第一行一个正整数n,表示数的数量。
第二行n个非负整数,表示鑫鑫给你的n个数。(2≤n≤100000,0≤ai≤108)
第二行n个非负整数,表示鑫鑫给你的n个数。(2≤n≤100000,0≤ai≤108)
输出
一行一个非负整数,表示答案。由于答案太大,你只需要输出答案对998244353(=7×17×223+1,一个质数)取模后的结果。
样例输入
5
1 2 3 4 5
样例输出
99
思路
这题我首先是发现任意两个数进行题意的操作后,所得的结果a'和b',a'^2+b'^2>=a^2+b^2。那么什么时候是大于呢,就是把a和b拆分成二进制,比如1和2吧,二进制为10和01,那么操作之后什么样呢,显然11和00啊,
就是尽可能的将二进制的1转移到一个或多个数上。那怎么是多个呢,就比如样例吧,两个7和一个1,因为最大就是三位二进制啊,111就是七啊,然后粘代码
代码如下:
1 #include <iostream> 2 #include <bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 const int maxn = 1e5+50; 6 const int mod = 998244353; 7 int a[maxn]; 8 int bit[50]; 9 int n,mlen=0; 10 inline int read() //读入优化 11 { 12 int x=0,f=1; 13 char c=getchar(); 14 while (!isdigit(c)) 15 f=c=='-'?-1:1,c=getchar(); 16 while (isdigit(c)) 17 x=(x<<1)+(x<<3)+(c^48),c=getchar(); 18 return x*f; 19 } 20 void solvebit() 21 { 22 for(register int i=1;i<=n;i++) 23 { 24 int cnt=0; 25 while(a[i]) 26 { 27 bit[++cnt]+=a[i]%2; 28 a[i]/=2; 29 } 30 mlen=max(mlen,cnt); 31 } 32 // for(register int i=1;i<=3;i++) 33 // cout << bit[i] << endl; 34 } 35 int main() 36 { 37 n=read(); 38 for(register int i=1;i<=n;i++) 39 { 40 a[i]=read(); 41 } 42 solvebit(); 43 ll all=0; 44 for(register int i=1;i<=n;i++) 45 { 46 ll base=1; 47 ll temp=0; 48 for(register int j=1;j<=mlen;j++) 49 { 50 if(bit[j]) 51 { 52 temp=(temp+base)%mod; 53 bit[j]--; 54 } 55 base*=2; 56 } 57 //cout << temp << endl; 58 all=(all+temp*temp%mod)%mod; 59 } 60 cout << all << endl; 61 //cout << "Hello world!" << endl; 62 return 0; 63 }