[方差+lucas定理] 51nod 算法马拉松25 D. 小Q的集合

题意

小Q有一个集合 S ,它的元素个数 |S|=n 。
对于 S 的任意一个子集合 T ,定义 f(T)=|T|k ,定义 T 关于 S 的补集为 S−T 。
小Q想知道,如果他等概率地选择一个 S 的子集 T ,那么 f(T)−f(S−T) 的方差是多少。
由于这个方差值可能很大,不妨设其为 v ,你只需要给出 (v2n)%m 的值即可。
k ≤ n ≤ 10^(10^6) , 1 ≤ k ≤ 10^6,其中m是质数,满足2 ≤ m ≤ 10^6。

题解

方差的定义: E[(xE(x))2] ,根据期望线性性质可化简为 E(x2)E(x)2
注意到E(x)恒为0,所以我们只需要计算 (E(x2)2n)%m 即可。
E(x2)2n=ni=0(ni)(ik(ni)k)2
注意到n很大,肯定不能直接求。
注意到右边的 (ik(ni)k)2 模m是循环的。但是前面还有一个组合数。
这里要用到lucas定理: (nm)=(n%Pm%P)(n/Pm/P)(modP)
这个定理比较适合模数小的问题。
对于i mod m相同的每一组, (n%Pi%P) 都是相同的。
按这个思路,可得
E(x2)2n
=n/mi=0n%mj=0(nim+j)((im+j)k(n(im+j))k)2
=n/mi=0n%mj=0(n/mi)(n%mj)((im+j)k(n(im+j))k)2
=n/mi=0(n/mi)n%mj=0(n%mj)(jk(nj)k)2
内层那个sigma就和i无关了,每次都是一样的,所以
=2n/mn%mj=0(n%mj)(jk(nj)k)2
直接求即可。

这题怎么卡常啊,半天才过……

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
int Nm,N_m,K,m,inv[1000005],powK[1000005],fac[1000015],ans;  //N_m == n%m  Nm == n/m 
char st[1000005];

inline LL power(int a,int b){
    LL res=1;
    for(LL w=a;b;w=w*w%m,b>>=1) if(b&1) res=(res*w)%m;
    return res;
}
inline LL C(int a,int b){
    return ((LL)fac[a])*inv[((LL)fac[b])*fac[a-b]%m]%m;
}
int main(){
    freopen("51nod25D.in","r",stdin);
    freopen("51nod25D.out","w",stdout);
    scanf("%s%d%d",st,&K,&m); K%=m-1;
    fac[0]=1; for(int i=1;i<=1000005;i++) fac[i]=((LL)fac[i-1])*i%m;
    inv[1]=1; for(int i=2;i<=m-1;i++) inv[i]=(LL)(m-m/i)*inv[m%i]%m;
    int len=strlen(st),t=0;
    for(int i=0;i<=len-1;i++){
        N_m=((N_m<<3)+(N_m<<1)+st[i]-'0')%m;
        t=(t<<3)+(t<<1)+st[i]-'0'; Nm=((Nm<<3)+(Nm<<1)+t/m)%(m-1); t%=m;
    }
    for(int i=0;i<=N_m;i++) powK[i]=power(i,K);
    for(int j=0;j<=N_m;j++){
        int num=powK[j]-powK[N_m-j];
        ans+=(C(N_m,j)*num%m)*num%m; ans%=m;
    }
    ans=(ans*power(2,Nm))%m;
    printf("%d\n",(ans+m)%m);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值