• 【BZOJ】1003 Cards


    【解析】Burnside引理+背包dp+乘法逆元


    [Analysis]
    这道题卡了好久,就是没想懂置换跟着色是不一样的。

    依据burnside引理。在一个置换群作用下不等价类的个数为每一个置换作用下不动点个数的平均数。
    在这道题中:
    置换的对象 —— 每一个状态,标号为1—N(这里的N不是题目的N,而是状态的个数)。


    不动点 —— 前后染色状态全然同样的状态的个数。
    所以就是求经过变换后前后状态全然同样的个数。


    [Sum]

    Burnside引理几个注意的地方

    [1]什么是Burnside引理?
    [2]置换的对象是什么?
    [3]不动点意味着什么?
    [4]着色变换不是置换。


    [Code]

    <span style="font-size:18px;">/**************************************************************
        Problem: 1004
        User: y20070316
        Language: C++
        Result: Accepted
        Time:328 ms
        Memory:2164 kb
    ****************************************************************/
     
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
     
    const int N=70;
     
    int Sr,Sb,Sg,n,m,p; //Basic
    int map[N][N],d[N],v[N],cnt;    //Substitution
    int f[N][N][N]; //Damatic Programming
    int res;    //Answer
     
    inline int read(void)
    {
        int s=0,f=1; char c=getchar();
        for (;c<'0'||c>'9';c=getchar());
        for (;'0'<=c&&c<='9';c=getchar()) s=s*10+c-'0';
        return s*f;
    }
     
    void init(void)
    {
        Sr=read(),Sb=read(),Sg=read(),n=Sr+Sb+Sg;
        m=read(),p=read();
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++) map[i][j]=read();
        m++; for (int j=1;j<=n;j++) map[m][j]=j;
    }
     
    void work(void)
    {
        for (int i=1;i<=m;i++)
        {
            cnt=0; memset(v,0,sizeof v);
            memset(d,0,sizeof d);
             
            for (int j=1;j<=n;j++)
                if (!v[j])
                {
                    v[j]=d[++cnt]=1;
                    for (int k=map[i][j];k^j;k=map[i][k]) 
                        v[k]=1,d[cnt]++;
                }
                 
            memset(f,0,sizeof f); f[0][0][0]=1;
            for (int i=1;i<=cnt;i++)
                for (int j=Sr;j>=0;j--)
                    for (int k=Sb;k>=0;k--)
                        for (int q=Sg;q>=0;q--)
                        {
                            f[j][k][q]=0;
                            if (j>=d[i]) f[j][k][q]=(f[j][k][q]+f[j-d[i]][k][q])%p;
                            if (k>=d[i]) f[j][k][q]=(f[j][k][q]+f[j][k-d[i]][q])%p;
                            if (q>=d[i]) f[j][k][q]=(f[j][k][q]+f[j][k][q-d[i]])%p;
                        }
            res=(res+f[Sr][Sb][Sg])%p;
        }
    }
     
    int mi(int i,int j)
    {
        if (!j) return 1;
        int s=mi(i,j>>1);
        s=s*s%p;
        if (j&1) s=s*i%p;
        return s;
    }
     
    void print(void)
    {
        int inv=mi(m,p-2);
        res=res*inv%p;
        printf("%d
    ",(res+p)%p);
    }
     
    int main(void)
    {   
        init();
        work();
        print();
     
        return 0;
    }</span>


  • 相关阅读:
    Eclipse启动不了
    第三章Hibernate关联映射
    System Generator简介
    Chipscope使用
    总线及数据传输技术【待完善】
    多相滤波器
    notepad++与ISE/Vivado关联
    常用IP核
    〖Linux〗Qt+gsoap开发客户端程序,服务端地址设定的字符串转换处理
    〖Android〗OK6410a的Android HAL层代码编写笔记
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/6851767.html
Copyright © 2020-2023  润新知