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;
    }
  • 相关阅读:
    23.C++- 继承的多种方式、显示调用父类构造函数、父子之间的同名函数、virtual虚函数
    22.C++- 继承与组合,protected访问级别
    LeetCode-391. 完美矩形(使用C语言编译,详解)
    LeetCode-101.对称二叉树
    STM32-对芯片启动读保护,实现加密(详解)
    21.C++- "++"操作符重载、隐式转换之explicit关键字、类的类型转换函数
    20.C++- "&&","||"逻辑重载操作符的缺陷、","逗号重载操作符的分析
    19.C++-(=)赋值操作符、初步编写智能指针
    18.C++-[ ]操作符使用 、函数对象与普通函数区别(详解)
    ECMAScript 6.0基础入门教程
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3207580.html
Copyright © 2011-2022 走看看