Problem Description
In addition fond of programing, Jack also loves painting. He likes to draw many interesting graphics on the paper.
One day,Jack found a new interesting graph called Palindrome graph. No matter how many times to flip or rotate 90 degrees, the palindrome graph are always unchanged.
Jack took a paper with n*n grid and K kinds of pigments.Some of the grid has been filled with color and can not be modified.Jack want to know:how many ways can he paint a palindrome graph?
Input
There are several test cases.
For each test case,there are three integer n m k(0<n<=10000,0<=m<=2000,0<k<=1000000), indicate n*n grid and k kinds of pigments.
Then follow m lines,for each line,there are 2 integer i,j.indicated that grid(i,j) (0<=i,j<n) has been filled with color.
You can suppose that jack have at least one way to paint a palindrome graph.
Output
For each case,print a integer in a line,indicate the number of ways jack can paint. The result can be very large, so print the result modulo 100 000 007.
Sample Input
Sample Output
Author
FZU
Source
2012 Multi-University Training Contest 7
//题意:给定一个n*n的矩阵,对里面的格子染色(k种颜色),要满足任意水平或垂直翻转或旋转90(180,270,360),所得到的图形都一样。即要求图中心对称的。 现在对一些格子染色,那么会使得它的对称点(8种状态)颜色都固定了。 现在只要求出不固定颜色的那些点的个数num,方案数就是k^num。
//对于一个颜色对称的矩阵,其实只要它的左上1/4的矩形的一半(三角形)颜色固定,那么整个图都可以由这个小三角旋转、折叠得到。且这个小三角里面的所有点都互不关联的。它就是最初的num值,对于给出的m个染色点可以扫描每个点的对称点(折叠、旋转)看是都有落在那个小三角里,有的话num--。 时间复杂度O(m);
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<stack>
#include<vector>
#include<ctime>
using namespace std;
#define maxn 2005
#define LL __int64
#define M 100000007
struct node
{
int x,y;
}point[maxn];
int n,m,k;
map<int,bool>my;
bool OK(int x,int y,int tmp)
{
node aa[10];
aa[1].x=x,aa[1].y=y; //点的折叠、旋转得到的8种状态
aa[2].x=x,aa[2].y=tmp-y;
aa[3].x=tmp-x,aa[3].y=y;
aa[4].x=tmp-x,aa[4].y=tmp-y;
aa[5].x=y,aa[5].y=x;
aa[6].x=tmp-y,aa[6].y=x;
aa[7].x=y,aa[7].y=tmp-x;
aa[8].x=tmp-y,aa[8].y=tmp-x;
int i;
bool flag=false;
for(i=1;i<=8;i++)
if(aa[i].y>=aa[i].x&&aa[i].x<=tmp/2&&aa[i].y<=tmp/2) //判断已确定颜色的点是否落在上小三角里
if(!my[aa[i].x*10000+aa[i].y]) //排除重复计算,用map来标记点是否已经被标记过
{
flag=true;
my[aa[i].x*10000+aa[i].y]=true;
}
return flag;
}
LL mod_mult(LL a,LL r)
{
LL d=1;
while(r)
{
if(r&1) d=d*a%M;
r>>=1;
a=a*a%M;
}
return d%M;
}
int main()
{
int i,j;
while(~scanf("%d%d%d",&n,&m,&k))
{
int tmp=n;
if(n&1) tmp++;
LL num=(tmp/2)*(tmp/2+1)/2; //上小三角格子的个数
my.clear();
for(i=0;i<m;i++)
{
scanf("%d%d",&point[i].x,&point[i].y);
if(OK(point[i].x,point[i].y,tmp-1))
num--;
}
printf("%I64d\n",mod_mult(k,num));
}
return 0;
}