题目大意:给你n个点m条边c种颜色,问题在旋转同构下的染色数。其中点是在二维平面上的点。
题目思路:由于是旋转染色计数,所以,很明显是polay计数。
大体思路就是,先简化处理,将这个图移动到坐标原点。然后由于是正点旋转,要重合的话一定要是旋转0,90,180,270四种置换。(转化到原点,点的旋转特别方便),然后对于每种置换,判断每一个点,每一条边是不是重合。然后统计每一种置换中的循环节有多少个。
#include<bits/stdc++.h>
#define eps 1e-4
#define maxn 55
const long long mod = 1000000007;
using namespace std;
long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
if(a==0&&b==0) return -1;
if(b==0){x=1;y=0;return a;}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
long long mod_rev(long long a,long long n)
{
long long x,y;
long long d=extend_gcd(a,n,x,y);
if(d==1) return (x%n+n)%n;
else return -1;
}
struct NODE {
double x,y;
}p[maxn],px[maxn];
int mp[maxn][maxn];
int tmp[maxn][maxn];
int id[maxn];
int n,m;
long long c;
int main()
{
int t;
scanf("%d",&t);
while(t--) {
scanf("%d%d%lld",&n,&m,&c);
double rx=0.0,ry=0.0;
for(int i=1;i<=n;i++) {
scanf("%lf%lf",&p[i].x,&p[i].y);
rx+=p[i].x;
ry+=p[i].y;
}
rx/=n;
ry/=n;
for(int i=1;i<=n;i++) {
p[i].x-=rx;
p[i].y-=ry;
}
memset(mp,0,sizeof mp);
int x,y;
for(int i=1;i<=m;i++) {
scanf("%d%d",&x,&y);
mp[x][y]=mp[y][x]=1;
}
long long ans=1;
long long cnt=1;
for(int i=1;i<=n;i++) ans=ans*c%mod;
for(int k=1;k<=3;k++) {
int fa=1;
memset(id,0,sizeof id);
memset(tmp,0,sizeof tmp);
if(k==1)
for(int i=1;i<=n;i++) {
px[i].x=p[i].y;
px[i].y=-p[i].x;
}
if(k==2)
for(int i=1;i<=n;i++) {
px[i].x=-p[i].x;
px[i].y=-p[i].y;
}
if(k==3)
for(int i=1;i<=n;i++) {
px[i].x=-p[i].y;
px[i].y=p[i].x;
}
for(int i=1;i<=n&&fa;i++) {
int sa=0;
for(int j=1;j<=n&&!sa;j++) {
if(fabs(px[i].x-p[j].x)<eps&&fabs(px[i].y-p[j].y)<eps) {
sa=1;
id[j]=i;
break;
}
}
if(!sa) {
fa=0;
break;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j]==1)
tmp[id[i]][id[j]]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j]!=tmp[i][j])
fa=0;
if(fa) {
int tot=0;
for(int i=1;i<=n;i++) {
if(id[i]==-1) continue;
int tt=i;
while(id[tt]!=i&&tt!=-1) {
int temp=tt;
tt=id[tt];
id[temp]=-1;
}
id[tt]=-1;
tot++;
}
long long res=1;
for(int i=1;i<=tot;i++) res=res*c%mod;
ans=(ans+res)%mod;
cnt++;
}
}
ans=ans*mod_rev(cnt,mod)%mod;
printf("%lld\n",ans);
}
return 0;
}