hud 4365 Palindrome graph
题意:给出N*N个矩形,分成n*n个小矩形,然后给出M种颜色,每个小矩形可以涂一种颜色,并且有些小矩形已经涂完颜色,要保证这个大矩形无论是旋转还是反转都要保持不变,问有多少种染色方式。
思路:中心对称图形,呃,其实找到有多少个小矩形可以然不同的颜色但又能保持是中心对称图形就基本上解决了这道题,找这些小矩形也很简单,是看了标程给出的公式才想到的,就是每个大矩形的左上角的那些小矩形。
代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <map> #include <math.h> #define N 5005 #define INF 100000007 using namespace std ; typedef long long ll ; int mark[N][N] ; ll cal ( int x ) { return x * ( x + 1 ) / 2 ; } ll powx ( ll a , ll b ) { ll s = 1 ; while ( b > 0 ) { if ( b & 1 ) s = ( s * a ) % INF ; b >>= 1 ; a = ( a * a ) % INF ; } return s ; } int main() { int n , m , k ; int x , y ; map<pair<int,int>,int>mark; while ( scanf ( "%d%d%d" , &n , &m , &k ) != EOF ) { ll res = cal (( n + 1 ) / 2 ); //cout<<res<<endl ; //memset( mark , 0 , sizeof ( mark )); mark.clear(); for ( int i = 0 ; i < m ; i++ ) { scanf( "%d%d" , &x , &y ); if ( x > n - 1 - x )//将下面的点翻到上面 x = n - 1 - x ; if ( y > n - 1 - y )//将右边的点翻到左边 y = n - 1 - y ; if ( x > y )//将右下角的点翻到左上角 { int tem = x ; x = y ; y = tem ; } if ( !mark[make_pair(x,y)] )//查看是否这个点已经染色,如果没有,标记,然后res--; { mark[make_pair( x, y )] = 1 ;//不用vextor,直接开二维数组会超内存。 res-- ; } } printf ( "%I64d\n" , powx ( k , res )); } return 0 ; }