【JZOJ5414】幸运值

7 篇文章 0 订阅
2 篇文章 0 订阅

Description

校庆志愿者小Z在休息时间和同学们玩卡牌游戏。一共有n张卡牌,每张卡牌上有一个数Ai,每次可以从中选出k张卡牌。一种选取方案的幸运值为这k张卡牌上数的异或和。小Z想知道所有选取方案的幸运值之和除以998244353的余数。

Solution

显然每一位是独立的。

于是拆位考虑,每一个为上选择奇数个1的方案数乘以该位权值即可。组合数可以轻松解决

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 100010
#define mo 998244353
#define ll long long
using namespace std;
int cn[32];
ll jc[N],ny[N];
ll pow(ll x,int y){
    ll b=1;
    while(y){
        if(y&1) b=b*x%mo;
        y>>=1;
        x=x*x%mo;
    }
    return b;
}
ll c(int m,int n){
    if(m<n) return 0;
    return jc[m]*ny[m-n]%mo*ny[n]%mo;
}
int main()
{
    freopen("card.in","r",stdin);
    freopen("card.out","w",stdout);
    int n,k;
    scanf("%d %d",&n,&k);
    jc[0]=ny[0]=1;
    fo(i,1,n)
    {
        int x;
        scanf("%d",&x);
        fo(j,0,30)
        if(x&(1<<j)) cn[j]++;
        jc[i]=jc[i-1]*i%mo,ny[i]=pow(jc[i],mo-2);
    }
    ll ans=0;
    fo(j,0,30)
    {
        ll tmp=0;
        fo(i,1,k)
        tmp=(tmp+c(cn[j],i)*c(n-cn[j],k-i)%mo)%mo,i++;
        ans=(ans+(1<<j)%mo*tmp%mo)%mo;
    }
    printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值