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;
}

 

posted @ 2019-08-19 11:16  WeiAR  阅读(262)  评论(0编辑  收藏  举报