Palindrome graph
Time Limit: 1000 ms /Memory Limit: 32768 kb
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
3 0 2 4 2 3 1 1 3 1
Sample Output
8 3
这题给出的是一个轴对称和中心对称的网格,所以网格的涂法由网格的八分之一(把正方形根据对称轴切成八个直角三角形)决定。因为这八个一定是一样的。
但是确定这个直角三角形需要剔除里面被涂了的格子,而被涂了的格子坐标分布在整个正方形,所以需要转换。
最后有了要涂的三角形,也就有了剩下的格子数量num。num个格子涂k种颜色就是k^num。
AC代码:
#include <cstdio>
#include <cmath>
#include <map>
using namespace std;
struct point{
int i;
int j;
};
point filled[2002];//已经被涂了的点
map<int, bool> maze;//剔除重复点
//快速幂,把乘降解为加方便取模
//不知道直接取模可不可以
typedef long long ll;
const int p = 100000007;
ll mul(ll a, ll b){
ll ans = 0;
while(b){
if(b & 1) ans = (ans + a) % p;
a = (a + a) % p;
b >>= 1;
}
return ans;
}
ll power(ll a,ll b){
ll ans = 1;
ll base = a % p;
while(b){
if(b & 1) ans = mul(ans, base) % p;
base = mul(base, base) % p;
b >>= 1;
}
return ans;
}
int main()
{
int n, m, k;
while( scanf("%d%d%d", &n, &m, &k) != EOF)
{
int num(0);
for(int i = 0; i < m; i++)
scanf("%d%d", &filled[i].i, &filled[i].j);
//转换坐标到同一个三角形
if(n&1){
for(int i = 0; i < m; i++){
if(filled[i].i > n / 2 + 1)
filled[i].i = n - filled[i].i - 1;
if(filled[i].j > n / 2 + 1)
filled[i].j = n - filled[i].j - 1;
if(filled[i].j <= filled[i].i)
swap(filled[i].j, filled[i].i);
}
}else
for(int i = 0; i < m; i++){
if(filled[i].i >= n / 2)
filled[i].i = n - filled[i].i - 1;
if(filled[i].j >= n / 2)
filled[i].j = n - filled[i].j - 1;
if(filled[i].j <= filled[i].i)
swap(filled[i].j, filled[i].i);
}
//i * 1000 + j就可以一个数字保存两个坐标数字
maze.clear();
map<int, bool>::iterator ite;
for(int i = 0; i < m; i++)
maze[filled[i].i*10000+filled[i].j] = false;
if(n&1){//三角形格子总数
num = (1 + n/2 + 1)*(n/2+1)/2;
}
else{
num = (1 + n/2)*(n/2)/2;
}
for(ite = maze.begin(); ite != maze.end(); ite++)
num--;
printf("%lld\n", power(k, num));
}
return 0;
}