Palindrome graph

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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值