P5390 [Cnoi2019]数学作业
P5390 [Cnoi2019]数学作业
求子集异或和的和
拆成2进制,假设有x个数这一位为1,剩下n-x个数对答案没有贡献,对于这一位而言,对答案的贡献就是,x个数选奇数个数的方案数*2^(n-x).
由二项式定理,(1-1)^x=sigema(0,x) (-1)^i*(x,i)=0
选奇数个和选偶数个方案是相同的,总共是2^x,这样就是2^(x-1).
所以这一位的答案为:2^(x-1) * 2^(n-x)=2^(n-1)
所以对于所以所有位而言,总的答案就是所有数或起来*2^(n-1)
#include <iostream> #include <cstdio> #include <queue> #include <algorithm> #include <cmath> #include <cstring> #define P 998244353 #define N 3000010 #define p(a) putchar(a) #define For(i,a,b) for(long long i=a;i<=b;++i) //by war //2019.8.19 using namespace std; long long T,n,a[N],ans; void in(long long &x){ long long y=1;char c=getchar();x=0; while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();} x*=y; } void o(long long x){ if(x<0){p('-');x=-x;} if(x>9)o(x/10); p(x%10+'0'); } long long ksm(long long a,long long b){ long long r=1; while(b>0){ if(b&1) r=r*a%P; a=a*a%P; b>>=1; } return r; } signed main(){ in(T); while(T--){ in(n); ans=0; For(i,1,n){ in(a[i]); ans|=a[i]; } o(ans*ksm(2,n-1)%P);p('\n'); } return 0; }