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;
    }
  • 相关阅读:
    spring mvc valid
    记录一次springmvc 404
    用到的 git 命令
    tomcat java.lang.OutOfMemoryError: PermGen space
    angularjs 表单验证 和 页面初始化闪烁
    在jsp中 EL表达式不生效
    关于jsp中使用jstl的问题
    块级元素,内联元素和定位
    java学习第4天
    STL 常用集合算法
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3207580.html
Copyright © 2011-2022 走看看