noip模拟赛 回文图

来源:互联网 发布:linux文件夹同步工具 编辑:程序博客网 时间:2024/05/16 16:20

1. 回文图

(hui.pas/c/cpp)

【问题描述】

有一片透明玻璃,我们可以在上面涂色。涂色后,你可以对它做两种操作:

1.旋转,顺时针或逆时针旋转90度;

2.翻转,水平或垂直翻转180度;

不管进行多少次旋转或翻转,我们看到都是相同的图形,我们把这样的图形称为"回文图"

下图是操作示例。请注意,图中并不是回文图。

      

现在给你一块n*n的方格状透明玻璃和k种颜色的油漆。请你给每个方格都涂上颜色,涂完后得到一幅回文图。但是这块玻璃上有m个方格事先已被涂上了颜色,你不能修改它们。

请问,总共能画出多少种不同的回文图?

【输入】

第一行,三个空格间隔的整数n,m,k

接下来m行,每行两个整数xy表示坐标为(x,y)的格子已被涂上了颜色(0<=x,y<n)。

【输出】

一行,一个整数,表示方案总数,结果可能很大,请输出Mod 100 000 007后的结果。

【输入输出样例1

hui.in

hui.out

3 0 2

8

 

【输入输出样例2

4 2 3

1 1

3 1

3

【输入输出样例1说明】

 

【数据范围】

 对于50%的数据:   0<n<=500,0<=m<=100,0<k<=100000  

 对于100%的数据:  0<n<=10000,0<=m<=2000,0<k<=1000000


题解:这道题算是一个简简单单的数学题吧(虽然我没有做出来。。。),只需要考虑方阵的一个1/8区域就可以了,设这个区域中有p个空格,有k种颜色,那么答案就是p^k

注意点是mod不是1e9+7而是1e8+7,然后就是给出的已涂色的方格得先把它变换到处理的那个1/8区域去,然后判重,再确定是否p--

P.S:(这是对我自己说的)要是不懂的话,可以去极乐净土上找原题解

code:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cstdlib>#include<algorithm>#include<map> const int MAXN=10005;const int mod=100000007;typedef long long LL;using namespace std;int n,p,k,m,x,y,t;bool vis[5005][5005];  LL mul(LL a,LL b,LL p){    LL ans=0;    for(LL i=1;i<=b;i<<=1,a=(a<<1)%p)        if(b&i) ans=(ans+a)%p;    return ans;}LL ksm(LL a,LL k,LL p){    LL ans=1;    while(k)    {        if(k&1) ans=mul(ans,a,p);        a=mul(a,a,p); k>>=1;    }    return ans;}inline void addpoint(int x,int y){    if(x>t) x=n-1-x;    if(y>t) y=n-1-y;    if(x<y) swap(x,y);    if(!vis[x][y])        vis[x][y]=1,p--;}int main(){    scanf("%d%d%d",&n,&m,&k);    t=(n-1)>>1; p=(t+2)*(t+1)>>1;    for(int i=1;i<=m;i++)    {        scanf("%d%d",&x,&y);        addpoint(x,y);    }    printf("%lld",ksm(k,p,mod));}


原创粉丝点击