Colorful Toy
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 454 Accepted Submission(s): 165
For instance, consider coloring the following toy with 2 colors. The coordinates of the vertices are:
1. (0,0)
2. (1,0)
3. (0,1)
4. (-1,0)
5. (0,-1)
The toy has 6 edges: (1,2), (1,3), (2,3), (3,4), (4,5), (5,2).
As a 2D being, this toy has no symmetry. So there are 32 ways to color it. Had the first two edges been removed, there would be only 12 different ways.
You should output the answer modulo 109 + 7.
Each test case begins with three positive integers N (1 ≤ N ≤ 50), M (0 ≤ M ≤ N (N - 1)/2) and C(1 ≤ C ≤ 100).
Then follow N lines. Each line contains 2 integers in range [-10000,10000] describing a vertex.
Then follow M lines. Each line contains 2 integers in range [1,N] representing an edge. There are neither duplicate edges nor self-loops.
2014年鞍山區域賽的一道題。題意:給n個點以及n個點的座標,還有m條邊。問給這個圖形染色共有多少種方案(旋轉後相同被視爲一種情況)。由於每個點的座標都是整數,所以原圖形只可能通過旋轉90度,180度,270度後與自身重合,只有這三種情況可能會算重。所以只需要判斷這三種情況下旋轉圖形後是否與原圖形完全一樣即可。首先,先找到圖形的中心點,然後將每個點座標減去中心點座標,相當於將圖形移動到原點。然後枚舉三種情況下,觀察旋轉後的圖形是否與原來圖形完全重合(先判斷點,後判斷邊),同時將原來圖形每個點的new_num更新成當前旋轉後對應的是哪個點。然後得到perm序列,然後運用polya定理即可求解。
polya定理,可用來用m種顏色染一個圖形共有多少種方法,需要知道對應的置換羣,對於每種置換方法求出有多少個循環節,記爲f[i],答案就是( ∑m^a[i] )/總置換方法數|G| .
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
#define N 1000005
#define eps 0.000000000001
#define maxn 5000
using namespace std;
const long long mod=1000000007;
long long n,m,c;
struct node{
double x,y;
double new_x,new_y;
int num;
int new_num;
}a[maxn];
int vis[maxn];
bool map[maxn][maxn];
int perm[maxn];
long long mul_pow(long long aa,long long bb)
{
long long d,t;
d=1;
t=aa;
while (bb>0)
{
if (bb%2==1)
d=(d*t)%mod;
bb/=2;
t=(t*t)%mod;
}
return d;
}
ll DFS()
{
int pos;
ll sum=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
perm[i]=a[i].new_num;
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
sum++;
pos=i;
for(int j=1;!vis[perm[pos]];j++)
{ pos=perm[pos];
vis[pos]=1;
}
}
}
return sum;
}
int main()
{
//freopen("E:in.txt","r",stdin);
//freopen("E:out1.txt","w",stdout);
int T;
double x,y,xx,yy;
scanf("%d",&T);
while(T--)
{
memset(map,0,sizeof(map));
memset(a,0,sizeof(a));
xx=0.0;yy=0.0;
scanf("%I64d%I64d%I64d",&n,&m,&c);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&x,&y);
a[i].x=x;a[i].y=y;
xx+=x;yy+=y;
a[i].num=i;
}
xx=xx/((double)n);yy=yy/((double)n);
for(int i=1;i<=n;i++)
{
a[i].x-=xx;a[i].y-=yy;
}
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
map[u][v]=1;map[v][u]=1;
}
int tmp=1;
long long ans=0;
ans=mul_pow(c,n);
for(int ca=1;ca<=3;ca++)
{
int flag=0;
for(int i=1;i<=n;i++)
{
if(flag)
break;
if(ca==1)
{
a[i].new_x=a[i].y;a[i].new_y=-a[i].x;
}
if(ca==2)
{
a[i].new_x=-a[i].x;a[i].new_y=-a[i].y;
}
if(ca==3)
{
a[i].new_x=-a[i].y;a[i].new_y=a[i].x; }
int fuck=0;
for(int j=1;j<=n;j++)
{
if(fabs(a[i].new_x-a[j].x)<eps&&fabs(a[i].new_y-a[j].y)<eps)
{
fuck=1;
a[j].new_num=i;
break;
}
// else flag=1;
}
if(fuck==0)
flag=1;
}
if(flag)
continue;
for(int i=1;i<=n;i++)
{
if(flag)
break;
for(int j=1;j<=n;j++)
{
if(map[i][j]!=map[a[i].new_num][a[j].new_num])
{
flag=1;break;
}
}
}
if(flag)
continue;
tmp++;
ll now=DFS();
ans+=mul_pow(c,now);
ans%=mod;
}
ans=ans*(mul_pow(tmp,mod-2))%mod;
printf("%I64d\n",ans);
}
}