题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4365
2012 年多校 第7场 1006题。
YY找规律,找完直接 快速幂。
题意有k中颜色让你在n*n的矩阵中填色,必须 旋转或者翻转 之后,矩阵颜色布置不变。
那么,很显然,我们需要去找,矩阵中有多少个 不管旋转还是翻转,都不会重合的点。
那么这些不重合的点有 N = ( n+3 ) * ( n+1 ) / 8 个。(粗算,整合后的公式,不知结果有木有变,比赛时推的是: ( (n+1)/2 +1) * ( (n+1)/2 ) / 2 )
然后告诉你已经有m个染好色了,那么此时你只需要判断这m个点里有多少个点旋转或翻转之后不会重合,假设我们得到的结果是M。
于是,这题的答案就是: k ^ ( N - M ) 。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstring>
#define f(x) ((x)>nn?n-(x)+1:(x));
using namespace std;
const int mod=100000007;
struct Point{
int x,y;
}node[3000];
int cmp(Point a,Point b){
return a.x!=b.x?a.x<b.x:a.y<b.y;
}
__int64 deal(int k,int cnt){
__int64 res=1,tmp=k;
while(cnt){
if(cnt&1)
res=(res*tmp)%mod;
tmp=(tmp*tmp)%mod;
cnt>>=1;
}
return res;
}
int main(){
int n,m,k,cnt,i,x,y,nn;
__int64 res;
while(~scanf("%d%d%d",&n,&m,&k)){
nn=(n+1)>>1;
for(i=0;i<m;i++){
scanf("%d%d",&node[i].x,&node[i].y);
node[i].x=f(node[i].x+1);
node[i].y=f(node[i].y+1);
if(node[i].x>node[i].y) swap(node[i].x,node[i].y);
}
sort(node,node+m,cmp);
if(m){
cnt=1;
for(i=1;i<m;i++)
if(node[i].x!=node[i-1].x || node[i].y!=node[i-1].y)
cnt++;
}
else cnt=0;
cnt=(nn+1)*nn/2-cnt;
if(cnt<0) cnt=0;
printf("%I64d\n",deal(k,cnt));
}
return 0;
}