HYSBZ/BZOJ 1004 [HNOI2008] Cards - 组合数学

来源:互联网 发布:淘宝内衣真人秀视频 编辑:程序博客网 时间:2024/06/10 18:23

题目描述

分析:

输入数据保证任意多次洗牌都可用这 m种洗牌法中的一种代替,且对每种洗牌法,都存在一种洗牌法使得能回到原状态。

这句话是说:
(1). m种洗牌方式保证能把所有排列的变换出来,且每种洗牌方式仅且仅用一次就够了,即不用多种洗牌方式叠加使用。
(2). 对于一个排列A,通过m种不同的变换可以得到(m+1)种不同的排列(包含A本身),而且,这(m+1)种排列能且只能由这(m+1)种排列通过变换得到。

Solution 1参考 by Liu Junhao:

在n张牌中一定要有Sr张red,Sb张blue,Sg张green
方案总数记为S

S=C(Sr,n)C(Sb,nSr)C(Sg,nSrSb)

=C(Sr,n)C(Sb,nSr)C(Sg,Sg)

=C(Sr,n)C(Sb,nSr)

由于其中(m+1)种算同一种,
ans=Sm+1modp

注意题目给出:p是质数,m+1< p => gcd(m+1,p)=1
由费马小定理可得:
(m+1)p11(modp)

即 m+1的乘法逆元为
(m+1)p2

可以做了。

#include<cstdio>int Sr,Sb,Sg,m,p,n,ans;int mypow(int x,int k){    int ret=1;    x%=p;    while(k){        if(k&1)            ret=ret*x%p;        x=x*x%p;        k>>=1;    }    return ret;}int main(){    scanf("%d%d%d%d%d",&Sr,&Sb,&Sg,&m,&p);    n=Sr+Sb+Sg;    for(int i=1;i<=m;i++)        for(int j=1;j<=n;j++)            scanf("%d",&ans);    long long t=1;    for(int i=1;i<=Sr;i++)        t=t*(n-i+1)/i;    ans=t%p;    n-=Sr;    t=1;    for(int i=1;i<=Sb;i++)        t=t*(n-i+1)/i;    ans=ans*(t%p)%p;    ans=ans*mypow(m+1,p-2)%p;    printf("%d\n",ans);}

Solution 2:

题解让用 置换 ,要用到Burnside引理,还要用到dp,仍然要用到乘法逆元。而且,没看懂。。。。。。。。。

0 0
原创粉丝点击