zoukankan      html  css  js  c++  java
  • BZOJ1004 [HNOI2008]Cards(Polya计数)

    枚举每个置换,求在每个置换下着色不变的方法数,先求出每个循环的大小,再动态规划求得使用给定的颜色时对应的方法数。

    dp[i][j][k]表示处理到当前圈时R,B,G使用量为i,j,k时的方法数,背包思想。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<utility>
    using namespace std;
    typedef long long LL;
    const int N = 68, INF = 0x3F3F3F3F;
    #define MS(a, num) memset(a, num, sizeof(a))
    #define PB(A) push_back(A)
    #define FOR(i, n) for(int i = 0; i < n; i++)
    int r, g, b, m, p, n;
    int dis[N][N];
    bool vis[N];
    LL dp[N][N][N];
    
    LL Ext_gcd(LL a,LL b,LL &x,LL &y){//扩展欧几里得
       if(b==0) { x=1, y=0; return a; }
       LL ret= Ext_gcd(b,a%b,y,x);
       y-= a/b*x;
       return ret;
    }
    LL Inv(LL a,int m){   ///求逆元
       LL d,x,y,t= (LL)m;
       d= Ext_gcd(a,t,x,y);
       if(d==1) return (x%t+t)%t;
       return -1;
    }
    
    LL solve(){
        LL ans = 0;
        for(int x = 0; x < m; x++){
            memset(vis, 0, sizeof(vis));
            vector<int> v;
            for(int i = 1; i <= n; i++){
                if(!vis[i]){
                    int cnt = 0;
                    int tp = i;
                    while(!vis[tp]){
                        cnt++;
                        vis[tp] = 1;
                        tp = dis[x][tp];
                    }
                    v.push_back(cnt);
                }
            }
            memset(dp, 0, sizeof(dp));
            dp[0][0][0] = 1;
            for(int t = 0; t < v.size(); t++){
                for(int i = r; i >= 0; i--){
                    for(int j = b; j >= 0; j--){
                        for(int k = g; k >= 0; k--){
                            if(i == 0 && j == 0 && k == 0){
                                continue;
                            }
                            dp[i][j][k] = 0;
                            if(i >= v[t]){
                                dp[i][j][k] = (dp[i][j][k] + dp[i - v[t]][j][k]) % p;
                            }
                            if(j >= v[t]){
                                dp[i][j][k] = (dp[i][j][k] + dp[i][j - v[t]][k]) % p;
                            }
                            if(k >= v[t]){
                                dp[i][j][k] = (dp[i][j][k] + dp[i][j][k - v[t]]) % p;
                            }
                        }
                    }
                }
            }
            ans = (ans + dp[r][b][g]) % p;
        }
        ans = ans * Inv(m, p) % p;
        return ans;
    }
    int main(){
        while(~scanf("%d %d %d %d %d", &r, &b, &g, &m, &p)){
            n = r + b + g;
            bool f = 1;
            for(int i = 0; i < m; i++){
                int cnt = 0;
                for(int j = 1; j <= n; j++){
                    scanf("%d", &dis[i][j]);
                    if(dis[i][j] == j){
                        cnt++;
                    }
                }
                if(cnt == n){
                    f = 0;
                }
            }
            if(f){
                for(int i = 1; i <= n; i++){
                    dis[m][i] = i;
                }
                m++;
            }
            printf("%lld
    ", solve());
        }
        return 0;
    }
    

      

  • 相关阅读:
    在TreeView控件节点中显示图片
    PAT 甲级 1146 Topological Order (25 分)
    PAT 甲级 1146 Topological Order (25 分)
    PAT 甲级 1145 Hashing
    PAT 甲级 1145 Hashing
    PAT 甲级 1144 The Missing Number (20 分)
    PAT 甲级 1144 The Missing Number (20 分)
    PAT 甲级 1151 LCA in a Binary Tree (30 分)
    PAT 甲级 1151 LCA in a Binary Tree (30 分)
    PAT 甲级 1149 Dangerous Goods Packaging
  • 原文地址:https://www.cnblogs.com/IMGavin/p/5863334.html
Copyright © 2011-2022 走看看