您的位置:首页 > 其它

【JZOJ5414】幸运值

2017-10-24 08:20 162 查看

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
,ny
;
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
%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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: