zoukankan      html  css  js  c++  java
  • 【BZOJ1004】Cards(HNOI2008)-Burnside引理+DP+逆元

    测试地址:Cards
    做法:本题需要用到Burnside引理+DP+逆元。
    注意到,按照题目中给的定义,给出的m个置换加上回到自身的置换合在一起是一个大小为m+1的置换群,那么我们可以DP求出对于每个置换的等价类数目,然后使用Burnside引理求出最后答案。至于怎么DP,只要先求出每个置换中各个循环内的元素的个数,然后就可以使用O(n4)的三维背包求出了(这里n的最大值视为20,因为每种牌最多只有20张)。最后要乘上一个1/(m+1),转化成乘上m+1p的逆元即可。总的时间复杂度为O(mn4)
    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int a,b,c,m,p,n,x[110];
    int f[65][25][25][25],g[65],ans=0;
    bool vis[65];
    
    int power(int a,int b)
    {
        int s=1,ss=a;
        while(b)
        {
            if (b&1) s=(s*ss)%p;
            b>>=1;ss=(ss*ss)%p;
        }
        return s;
    }
    
    void work()
    {
        int tot=0;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
            if (!vis[i])
            {
                g[++tot]=0;
                int now=i;
                while(!vis[now]) vis[now]=1,g[tot]++,now=x[now];
            }
        memset(f,0,sizeof(f));
        f[0][0][0][0]=1;
        for(int i=1;i<=tot;i++)
        {
            for(int sa=0;sa<=a;sa++)
                for(int sb=0;sb<=b;sb++)
                    for(int sc=0;sc<=c;sc++)
                    {
                        if (sa>=g[i]) f[i][sa][sb][sc]=(f[i][sa][sb][sc]+f[i-1][sa-g[i]][sb][sc])%p;
                        if (sb>=g[i]) f[i][sa][sb][sc]=(f[i][sa][sb][sc]+f[i-1][sa][sb-g[i]][sc])%p;
                        if (sc>=g[i]) f[i][sa][sb][sc]=(f[i][sa][sb][sc]+f[i-1][sa][sb][sc-g[i]])%p;
                    }
        }
        ans=(ans+f[tot][a][b][c])%p;
    }
    
    int main()
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&m,&p);
        n=a+b+c;
        for(int i=1;i<=n;i++) x[i]=i;
        work();
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++) scanf("%d",&x[j]);
            work();
        }
        ans=(power(m+1,p-2)*ans)%p;
        printf("%d",ans);
    
        return 0;
    }
  • 相关阅读:
    Go语言基础之切片
    Go语言基础之map
    Go语言基础之函数
    Go语言基础之指针
    Go语言基础之结构体
    Redis缓存失效策略
    redis 的过期策略都有哪些?内存淘汰机制都有哪些?
    关于redis的主从、哨兵、集群
    Redis的 RDB和 AOF持久化的区别
    为什么做分布式使用 Redis
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793549.html
Copyright © 2011-2022 走看看