poj 2888 Magic Bracelet(Polya+矩阵快速幂)

时间:2023-03-09 19:27:32
poj 2888 Magic Bracelet(Polya+矩阵快速幂)
Magic Bracelet
Time Limit: 2000MS   Memory Limit: 131072K
Total Submissions: 4990   Accepted: 1610

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

/*
poj 2888 Magic Bracelet(Polya+矩阵快速幂) 给你m个不同的珠子组成一个长度为n的项链 (个人理解),只考虑旋转的情况下总共能够成
多少种不同的项链。 而且规定有的珠子不能挨在一起 大致还是Polya计数,只是要想办法解决找出长度为i的循环节有多少个。于是乎可以考虑
矩阵快速幂(一个经典问题:解决m步从a走到b的方案数) 主要是一直TLE,知道后来把euler改成通过素数求才过- -. 而且取模过多好像也会TLE hhh-2016-04-19 22:31:42
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
using namespace std;
#define lson (i<<1)
#define rson ((i<<1)|1)
//typedef long long ll;
using namespace std;
const int maxn = ;
struct Matrix
{
int ma[][];
}; int n,m;
int isprime[maxn];
int prime[maxn];
int pnum;
void get_prime()
{
pnum = ;
memset(isprime, -, sizeof(isprime));
for(int i = ; i <= maxn-; i ++)
if(isprime[i])
{
prime[pnum ++] = i;
for(int j = i * i; j <= maxn-; j += i)
isprime[j] = ;
}
} Matrix mult(Matrix ta,Matrix tb, int mod)
{
Matrix tc;
memset(tc.ma,,sizeof(tc.ma));
for(int i = ; i < m; i ++)
for(int k = ; k < m; k ++)
if(ta.ma[i][k])
{
for(int j = ; j < m; j ++)
if(tb.ma[k][j])
tc.ma[i][j] = (tc.ma[i][j] + ta.ma[i][k] * tb.ma[k][j]) % mod;
}
return tc;
} Matrix Mat_pow(Matrix ta,int n,int mod)
{
Matrix t;
memset(t.ma,,sizeof(t.ma));
for(int i = ; i < m; i++)
t.ma[i][i] = ;
while(n)
{
if(n & ) t = mult(t,ta,mod);
ta = mult(ta,ta,mod);
n >>= ;
}
return t;
} int pow_mod(int a,int n,int mod)
{
int ret = ;
a %= mod;
while(n)
{
if(n & ) ret = ret*a,ret%=mod;
a = a*a;
a%=mod;
n >>= ;
}
return ret;
}
int mod;
int euler(int cur )
{
int ans, x;
ans = x = cur;
for(int i = ; i < pnum && prime[i] * prime[i] <= cur; i++)
if(x % prime[i] == )
{
ans = ans / prime[i] * (prime[i] - );
while(x % prime[i] == )
x /= prime[i];
}
if(x > )
ans = ans / x * (x - );
return ans%mod;
} Matrix mat;
int cal(int len)
{
int ret = ;
Matrix t = Mat_pow(mat,len,mod);
for(int i = ; i < m; i++)
ret = ret + t.ma[i][i];
ret %= mod; return ret;
} int Polya(int n)
{
int ans = ;
for(int i= ; i*i <= n; i++)
{
if(n % i == )
{
if(i*i == n)
{
ans = ans+cal(i)*euler(i);
ans%=mod;
}
else
{
ans = (ans+cal(i)*euler(n/i)+cal(n/i)*euler(i));
ans%=mod;
}
}
}
ans = ans*pow_mod(n,mod-,mod);
return ans % mod;
} int main()
{
int T;
get_prime();
mod = ;
scanf("%d",&T);
while(T--)
{
int k;
scanf("%d%d%d",&n,&m,&k);
int u,v;
for(int i = ; i < m; i++)
for(int j = ; j < m; j++)
mat.ma[i][j] = ;
for(int i = ; i <= k; i++)
{
scanf("%d%d",&u,&v);
mat.ma[u-][v-] = mat.ma[v-][u-] = ;
}
printf("%d\n",Polya(n));
}
return ;
}