zoukankan      html  css  js  c++  java
  • POJ 2888 Magic Bracelet(Burnside引理,矩阵优化)

    Magic Bracelet
    Time Limit: 2000MS   Memory Limit: 131072K
    Total Submissions: 3731   Accepted: 1227

    Description

    Ginny’s birthday is coming soon. Harry Potter is preparing a birthday present for his new girlfriend. The present is a magic bracelet which consists of n magic beads. The are m kinds of different magic beads. Each kind of beads has its unique characteristic. Stringing many beads together a beautiful circular magic bracelet will be made. As Harry Potter’s friend Hermione has pointed out, beads of certain pairs of kinds will interact with each other and explode, Harry Potter must be very careful to make sure that beads of these pairs are not stringed next to each other.

    There infinite beads of each kind. How many different bracelets can Harry make if repetitions produced by rotation around the center of the bracelet are neglected? Find the answer taken modulo 9973.

    Input

    The first line of the input contains the number of test cases.

    Each test cases starts with a line containing three integers n (1 ≤ n ≤ 109gcd(n, 9973) = 1), m (1 ≤ m ≤ 10), k (1 ≤ k ≤ m(m − 1) ⁄ 2). The next k lines each contain two integers a and b(1 ≤ ab ≤ m), indicating beads of kind a cannot be stringed to beads of kind b.

    Output

    Output the answer of each test case on a separate line.

    Sample Input

    4
    3 2 0
    3 2 1
    1 2
    3 2 2
    1 1
    1 2
    3 2 3
    1 1
    1 2
    2 2

    Sample Output

    4
    2
    1
    0

    Source

     
     
    很好的一道题目。
    做了这题才感觉对Burnside引理和polya定理有点深入了解。
     
     
    还不清楚的可以看看上面的链接,解释的很清楚。
     
    关于这题,给个解释的很清楚的http://hi.baidu.com/billdu/item/62319f2554c7cac9a5275a0d
     
    讲得很清晰
     
    #include <stdio.h>
    #include <algorithm>
    #include <string.h>
    #include <iostream>
    using namespace std;
    const int MOD = 9973;
    //矩阵
    struct Matrix
    {
        int mat[20][20];
        int n,m;
        Matrix(){}
        Matrix(int _n,int _m)
        {
            n = _n; m  = _m;
            for(int i = 0;i < n;i++)
                for(int j = 0;j < m;j++)
                    mat[i][j] = 0;
        }
        Matrix operator *(const Matrix &b)const
        {
            Matrix ret = Matrix(n,b.m);
            for(int i = 0;i < ret.n;i++)
                for(int j = 0;j < ret.m;j++)
                {
                    for(int k = 0;k < m;k++)
                    {
                        ret.mat[i][j] += mat[i][k]*b.mat[k][j];
                        ret.mat[i][j] %= MOD;
                    }
                }
            return ret;
        }
        Matrix operator ^(int b)const
        {
            Matrix ret = Matrix(n,m),tmp = Matrix(n,m);
            for(int i = 0;i < n;i++)
            {
                for(int j = 0;j < m;j++)
                    tmp.mat[i][j] = mat[i][j];
                ret.mat[i][i] = 1;
            }
            while(b)
            {
                if(b&1)ret = ret*tmp;
                tmp = tmp*tmp;
                b >>= 1;
            }
            return ret;
        }
    };
    //求欧拉函数
    long long eular(long long n)
    {
        long long ans = n;
        for(int i = 2;i*i <= n;i++)
        {
            if(n % i == 0)
            {
                ans -= ans/i;
                while(n % i == 0)
                    n /= i;
            }
        }
        if(n > 1)ans -= ans/n;
        return ans;
    }
    //快速幂,用来求逆元
    long long pow_m(long long a,long long n,long long mod)
    {
        long long ret = 1;
        long long tmp = a%mod;
        while(n)
        {
            if(n&1)
            {
                ret *= tmp;
                ret %= mod;
            }
            tmp *= tmp;
            tmp %= mod;
            n>>=1;
        }
        return ret;
    }
    //利用欧拉定理求逆元
    long long inv(long long x,long long mod)//mod为素数
    {
        return pow_m(x,mod-2,mod);
    }
    
    Matrix A,B;
    int n,m;
    //求x个元素对应的f
    int NoChange(int x)
    {
        B = A^x;
        int ans = 0;
        for(int i = 0; i < m;i++)
        {
            ans += B.mat[i][i];
            ans %= MOD;
        }
        return ans;
    }
    int solve()
    {
        int ans = 0;
        for(int i = 1;i*i <= n;i++)
            if(n % i == 0)
            {
                ans = ans + eular(i)*NoChange(n/i)%MOD;
                ans %= MOD;
                if(n/i != i)
                {
                    ans = ans + eular(n/i)*NoChange(i)%MOD;
                    ans %= MOD;
                }
            }
        ans *= inv(n,MOD);
        return ans%MOD;
    }
    int main()
    {
        int T;
        int k;
        int u,v;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&k);
            A = Matrix(m,m);
            for(int i = 0;i < m;i++)
                for(int j = 0;j < m;j++)
                    A.mat[i][j] = 1;
            while(k--)
            {
                scanf("%d%d",&u,&v);
                u--;
                v--;
                A.mat[u][v] = A.mat[v][u] = 0;
            }
            printf("%d
    ",solve());
        }
        return 0;
    }
  • 相关阅读:
    centos、mac的grafana安装和简单使用
    通过k8s(Kubernetes)搭建jmeter的压测环境master-slave架构,实现弹性伸缩
    burpsuite破解版
    jvm调优
    火狐firefox、谷歌chrome等浏览器扩展、插件介绍
    关于Chrome谷歌浏览器开发者工具网络Network中返回无数据的问题
    微博登录过程分析
    SQL SERVER大话存储结构(4)_复合索引与包含索引
    千万级别数据表,单列索引和多列索引性能对比
    Showplan 逻辑运算符和物理运算符参考
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3207580.html
Copyright © 2011-2022 走看看