[POJ 2888] Magic Bracelet

Magic Bracelet
Time Limit: 2000MS   Memory Limit: 131072K
Total Submissions: 4727   Accepted: 1533

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 ≤ 109, gcd(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 ≤ a, b ≤ 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

POJ Monthly--2006.07.30, cuiaoxiang
 
一定要理解Burnside定理(不知道拼对没有)、不理解一定不会做、做了不一定能完全理解
#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

#define ll long long

#define N 32000



struct Matric

{

    int size;

    int a[12][12];

    Matric(int s=0)

    {

        size=s;

        memset(a,0,sizeof(a));

    }

    Matric operator * (const Matric &t)

    {

        Matric res=Matric(size);

        for(int i=0;i<size;i++)

        {

            for(int k=0;k<size;k++)

            {

                if((*this).a[i][k])

                    for(int j=0;j<size;j++)

                    {

                        res.a[i][j]+=(*this).a[i][k]*t.a[k][j];

                        if(res.a[i][j]>=9973) res.a[i][j]%=9973;

                    }

            }

        }

        return res;

    }

    Matric operator ^ (int n)

    {

        Matric ans=Matric(size);

        for(int i=0;i<size;i++) ans.a[i][i]=1;

        while(n)

        {

            if(n&1) ans=ans*(*this);

            (*this)=(*this)*(*this);

            n>>=1;

        }

        return ans;

    }

    int CalNum(int k)

    {

        Matric tmp=(*this);

        tmp=tmp^k;

        int ans=0;

        for(int i=0;i<size;i++)

        {

            ans=(ans+tmp.a[i][i])%9973;

            if(ans>=9973) ans%=9973;

        }

        return ans;

    }

};

int tot;

int prime[N+10];

bool isprime[N+10];

int phi[N+10];

void prime_pri()

{

    tot=0;

    phi[1]=1;

    memset(isprime,true,sizeof(isprime));

    isprime[0]=isprime[1]=false;

    for(int i=2;i<=N;i++)

    {

        if(isprime[i])

        {

            prime[tot++]=i;

            phi[i]=i-1;

        }

        for(int j=0;j<tot;j++)

        {

            if((ll)i*prime[j]>N) break;

            isprime[i*prime[j]]=false;

            if(i%prime[j]==0)

            {

                phi[i*prime[j]]=phi[i]*prime[j];

                break;

            }

            else

            {

                phi[i*prime[j]]=phi[i]*(prime[j]-1);

            }

        }

    }

}

int euler(int n)

{

    if(n<=N) return phi[n];

    int ret=n;

    for(int i=0;(ll)prime[i]*prime[i]<=n;i++)

    {

        if(n%prime[i]==0)

        {

            ret-=ret/prime[i];

            while(n%prime[i]==0) n/=prime[i];

        }

    }

    if(n>1) ret-=ret/n;

    return ret;

}

int exgcd(int a,int b,int& x, int& y)

{

    if(b==0)

    {

        x=1;

        y=0;

        return a;

    }

    int d=exgcd(b,a%b,y,x);

    y-=a/b*x;

    return d;

}

int inv(int a,int MOD)

{

    int x,y;

    exgcd(a,MOD,x,y);

    x=(x%MOD+MOD)%MOD;

    return x;

}

int main()

{

    prime_pri();

    int T;

    int n,m,k;

    int MOD=9973;

    scanf("%d",&T);

    while(T--)

    {

        scanf("%d%d%d",&n,&m,&k); //n个点,m种颜色,k种限制

        Matric a=Matric(m);

        for(int i=0;i<m;i++) for(int j=0;j<m;j++) a.a[i][j]=1;

        for(int i=0;i<k;i++)

        {

            int u,v;

            scanf("%d%d",&u,&v);

            a.a[u-1][v-1]=a.a[v-1][u-1]=0;

        }

        int ans=0;

        for(int i=1;i*i<=n;i++)

        {

            if(n%i==0)

            {

                if(i*i==n)

                    ans+=ans+euler(i)%MOD*a.CalNum(i);

                else

                    ans+=euler(i)%MOD*a.CalNum(n/i)+euler(n/i)%MOD*a.CalNum(i);

                if(ans>=9973) ans%=9973;

            }

        }

        ans=ans*inv(n,MOD)%MOD;

        printf("%d\n",ans);

    }

    return 0;

}

 

你可能感兴趣的:(poj)