Magic Bracelet
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
|
[Submit] [Go Back] [Status] [Discuss]
题目大意:给n元环染色,求有多少本质不同的染色方案(旋转后相同即算本质相同),且要求a,b颜色不能相连。
题解:矩阵乘法+置换
C(f)要求一个置换中的颜色是必须相同的。这道题计算答案的方式与hdu 2865,主要是f数组的计算方式不同。
我们还是考虑用矩阵来做。把颜色的选择看成生成一条路径,如果a,b颜色不能相连,那么f[a][b]=f[b][a]=0,剩下的都是1,直接进行矩阵。注意统计答案的时候跳过a,b不能相连的位置,因为我们实际形成的应该是个首尾相连的环。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 1000003
#define p 9973
#define LL long long
using namespace std;
int n,m,T,k;
int phi[N],prime[N],pd[N];
struct data{
int a[20][20];
}ch,e,b;
void init(int n)
{
phi[1]=1;
for (int i=2;i<=n;i++) {
if (!pd[i]) {
prime[++prime[0]]=i;
phi[i]=i-1;
}
for (int j=1;j<=prime[0];j++) {
if (i*prime[j]>n) break;
pd[i*prime[j]]=1;
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 getphi(int x)
{
if (x<=1000000) return phi[x]%p;
LL ans=x;
for (int i=1;prime[i]*prime[i]<=x;i++)
if (x%prime[i]==0) {
ans=(LL)ans/(LL)prime[i]*(LL)(prime[i]-1);
while (x%prime[i]==0) x/=prime[i];
}
if (x>1) ans=(LL)ans/(LL)x*(LL)(x-1);
return ans%p;
}
void clear(data &a)
{
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++) a.a[i][j]=e.a[i][j];
}
data mul(data a,data b)
{
data c;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++) {
c.a[i][j]=0;
int (*w)=&(c.a[i][j]); (*w)=0;
for (int k=1;k<=m;k++)
(*w)=((*w)+a.a[i][k]*b.a[k][j])%p;
}
return c;
}
data quickpow(data num,int x)
{
data ans; clear(ans);
data base; base=num;
while (x) {
if (x&1) ans=mul(ans,base);
x>>=1;
base=mul(base,base);
}
return ans;
}
int calc(int i)
{
if (i==1) {
int ans=0;
for (int i=1;i<=m;i++) {
ans=ans+ch.a[i][i];
if (ans>=p) ans-=p;
}
return ans;
}
data t=quickpow(ch,i-1);
int ans=0;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
if (ch.a[i][j]) {
ans=ans+t.a[i][j];
if (ans>=p) ans-=p;
}
return ans;
}
int quickpow(int num,int x)
{
int ans=1; int base=num%p;
while (x) {
if (x&1) ans=ans*base%p;
x>>=1;
base=base*base%p;
}
return ans;
}
int main()
{
freopen("a.in","r",stdin);
// freopen("my.out","w",stdout);
scanf("%d",&T); init(1000000);
for (int i=1;i<=10;i++) e.a[i][i]=1;
while (T--) {
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++) ch.a[i][j]=1;
for (int i=1;i<=k;i++) {
int x,y; scanf("%d%d",&x,&y);
ch.a[x][y]=ch.a[y][x]=0;
}
//for (int i=1;i<=m;i++,cout<<endl)
// for (int j=1;j<=m;j++) cout<<ch.a[i][j]<<" ";
int ans=0;
for (int i=1;i*i<=n;i++)
if (n%i==0){
ans+=calc(i)*getphi(n/i)%p; ans%=p;
//cout<<calc(i)<<" "<<getphi(n/i)<<endl;
if (i*i!=n) ans+=calc(n/i)*getphi(i)%p;
//cout<<calc(n/i)<<" "<<getphi(i)<<endl;
ans%=p;
}
ans=ans*quickpow(n,p-2)%p;
printf("%d\n",ans);
}
}