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;
    }
  • 相关阅读:
    SQL联结(Join)的命令详解
    Symbian c++在程序安装时显示一份免责声明
    Effective C++条款11: 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
    <转>S60系统出错问题汇总
    开发规范C#程序
    Javascript 进行decode编码,C#中进行解码的问题
    IIS7.5 不能访问3.5 wcf 的解决办法
    开发规范总结数据库
    [转载]Linux性能测试 tcpdump命令
    [转载]Linux性能测试 top命令
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3207580.html
Copyright © 2011-2022 走看看