[2017纪中10-23]幸运值 组合数学 位运算

来源:互联网 发布:餐厅排队叫号软件 编辑:程序博客网 时间:2024/06/01 21:52

题目链接:https://jzoj.net/senior/#main/show/5414
显然,每一位是独立的。对每一位分别考虑贡献。
那么,对于每一位,这些数中哪些是1哪些是0不重要,重要的是有几个1几个0。
假设第x位有b个1,n-b个0,求选出奇数个(不超过k)1的方案数。显然等于sigma(C(b,i)*C(n-b,k-i)){1<=i<=k且i为奇数}。
预处理阶乘和阶乘逆元。注意C(n,m)n < m的情况。
代码:

#include<iostream>#include<cstdio>#define ll long longusing namespace std;const int mod=998244353;const int maxn=100010;int n,k;ll jie[maxn],inv[maxn],a[maxn];ll ksm(ll a,int b){ll re=1;while(b){if(b&1) re=re*a%mod;a=a*a%mod;b>>=1;}return re;}int main(){    scanf("%d%d",&n,&k);    for(int i=1;i<=n;i++)        scanf("%lld",&a[i]);    jie[0]=inv[0]=1;    for(int i=1;i<=n;i++)    {        jie[i]=jie[i-1]*i%mod;        inv[i]=ksm(jie[i],mod-2);    }    ll ans=0;    for(int i=0;i<=30;i++)    {        int b=0;        for(int j=1;j<=n;j++)            b+=((a[j]>>i)&1);               for(int j=1;j<=min(k,b);j++)            if(j&1&&n-b>=k-j)  ans=(ans+jie[b]*jie[n-b]%mod*inv[j]%mod*inv[b-j]%mod*inv[k-j]%mod*inv[n-b-k+j]%mod*(1ll<<i)%mod)%mod;        }    printf("%lld",ans);    return 0;}