HYSBZ/BZOJ 1004 [HNOI2008] Cards - 组合数学
分析:
输入数据保证任意多次洗牌都可用这 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
由于其中(m+1)种算同一种,
注意题目给出:p是质数,m+1< p => gcd(m+1,p)=1
由费马小定理可得:
即 m+1的乘法逆元为
可以做了。
#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,仍然要用到乘法逆元。而且,没看懂。。。。。。。。。