因为
n
很大,不能直接枚举旋转的次数
接下来考虑对于某个循环个数
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define LL long long
const int p=9973,maxx=100000;
int n,m,k,tot,have[maxx+10],prm[maxx+10];
struct mat
{
int a[12][12];
mat operator * (const mat &mm) const
{
mat ret;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
{
ret.a[i][j]=0;
for (int k=1;k<=m;k++)
ret.a[i][j]=(ret.a[i][j]+a[i][k]*mm.a[k][j])%p;
}
return ret;
}
mat pow(int x)
{
mat base,ret;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
{
base.a[i][j]=a[i][j];
ret.a[i][j]=(i==j);
}
for (;x;x>>=1,base=base*base)
if (x&1) ret=ret*base;
return ret;
}
int count()
{
int ret=0;
for (int i=1;i<=m;i++)
ret+=a[i][i];
return ret%p;
}
}f,g;
int pow(int base,int x)
{
int ret=1;
for (;x;x>>=1,base=base*base%p)
if (x&1) ret=ret*base%p;
return ret;
}
int phi(int x)
{
int ret=x;
for (int i=1;prm[i]*prm[i]<=x;i++)
if (x%prm[i]==0)
{
ret=ret/prm[i]*(prm[i]-1);
while (x%prm[i]==0) x/=prm[i];
}
if (x>1) ret=ret/x*(x-1);
return ret%p;
}
void solve()
{
int x,y,ans=0;
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
f.a[i][j]=1;
while (k--)
{
scanf("%d%d",&x,&y);
f.a[x][y]=f.a[y][x]=0;
}
for (int i=1;i*i<=n;i++)
if (n%i==0)
{
g=f.pow(i);
ans=(ans+phi(n/i)*g.count())%p;
if (i*i<n)
{
g=f.pow(n/i);
ans=(ans+phi(i)*g.count())%p;
}
}
printf("%d\n",ans*pow(n%p,p-2)%p);
}
int main()
{
int T;
for (int i=2;i<=maxx;i++)
{
if (!have[i]) prm[++tot]=i;
for (int j=1;j<=tot&&(LL)i*prm[j]<=maxx;j++)
{
have[i*prm[j]]=1;
if (i%prm[j]==0) break;
}
}
scanf("%d",&T);
while (T--) solve();
}