题意简述:给你N和M,对于一个N∗M的单面方格纸你能够对它的每

个个格子黑白染色。然后把方格纸的长边卷起来,卷成一个圆柱体,然后再把

两个短边形成的圆也接起来。形成一个游泳圈的形状(我们染的色仅仅在游泳圈

的外表面)。假设对于两种黑白染色方案。通过卷成这种游泳圈后,是一样

的。则这两种方案也是一样的。给定N,M<=20。求染色方案总数.

分析:

首先我们得会Pólya定理,參见http://wenku.baidu.com/view/bf92a95f804d2b160b4ec0be.html

依据题目的要求,分两种情况:

①若N=M,那么就有翻转0o,90o,180o,270o与上下移动,左右移动共N∗M∗2∗2种置换;

②若N≠M,那么就有翻转0o,180o与上下移动,左右移动共N∗M∗2种置换;

依据Pólya定理,我们分三步:

①暴力搜出全部置换;

②搜出全部置换的循环。

③把答案累加后除以置换数。

时间复杂度:

①O(N∗M)②O(N∗M)

因此总的为O((N∗M)2)

ps.我们须要写高精度。能够预处理2的幂来进行加速。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAXN = 29;
const int MAXM = 29;
const int MAXL = 200; int n, m; int G;
bool check_square;
int ex[MAXN*MAXM]; struct bigNum
{
int a[MAXL];
bigNum(){memset(a, 0, sizeof(a));a[0] = 1;}
inline void operator += (const bigNum &add)
{
a[0] = max(a[0], add.a[0]);
for(int i = 1; i <= a[0]; ++i)
{
a[i] += add.a[i];
a[i+1] += a[i]/10;
a[i] %= 10;
}
if(a[a[0]+1]) a[0]++;
}
inline void operator /= (int k)
{
for(int i = a[0]; i > 0; --i)
{
a[i-1] += a[i]%k*10;
a[i] /= k;
}
for(; a[0] > 0; --a[0])
if(a[a[0]]) return ;
}
inline void print()
{
for(int i = a[0]; i > 0; --i)
printf("%d", a[i]);
}
}ans, pow2[MAXN*MAXM]; inline void init()
{
scanf("%d%d", &n, &m);
if(n == m) G = n*m*4, check_square = true;
else G = n*m*2;
for(int i = 1; i <= n*m; ++i)
ex[i] = i;
} inline int calc()
{
int re = 0;
bool hash[MAXN*MAXM] = {false};
for(int i = 1; i <= n*m; ++i)
if(!hash[i])
{
for(int j = i; !hash[j]; j = ex[j])
hash[j] = true;
re++;
}
return re;
} inline void rotate()
{
int nex[MAXN*MAXM] = {0};
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
nex[(m-j)*n+i] = ex[(i-1)*m+j];
for(int i = 1; i <= n*m; ++i) ex[i] = nex[i];
swap(n, m);
} inline void shift_down()
{
int nex[MAXN*MAXM] = {0};
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
nex[(i%n)*m+j] = ex[(i-1)*m+j];
for(int i = 1; i <= n*m; ++i) ex[i] = nex[i];
} inline void shift_right()
{
int nex[MAXN*MAXM] = {0};
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
nex[(i-1)*m+j%m+1] = ex[(i-1)*m+j];
for(int i = 1; i <= n*m; ++i) ex[i] = nex[i];
} inline void work()
{
pow2[0].a[0] = pow2[0].a[1] = 1;
for(int i = 1; i <= n*m; ++i)
{
bigNum tmp = pow2[i-1];
tmp += pow2[i-1];
pow2[i] = tmp;
}
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= m; ++j)
{
ans += pow2[calc()];
rotate();
if(check_square) ans += pow2[calc()];
rotate();
ans += pow2[calc()];
rotate();
if(check_square) ans += pow2[calc()];
rotate();
shift_right();
}
shift_down();
}
ans /= G;
} inline void print()
{
ans.print();
puts("");
} int main()
{
init();
work();
print();
return 0;
}

最新文章

  1. jQuery -原生 如何互转
  2. java web后台开发SSM框架(Spring+SpringMVC+MyBaitis)搭建与优化
  3. mysql 根据某些字段之和排序
  4. u1-nav-css
  5. java中&amp;和&amp;&amp;的区别和联系
  6. Paragon NTFS for Mac免费获取官方赠送正版.更新获取ntfs for mac 14方法
  7. 一个tomcat上放多个webapp问题,那这多个webapp会不会竞争端口呢?不会!安全两码事
  8. HTML5每日一练之figure新标签的应用
  9. 1028. List Sorting (25)
  10. 关于MANIFEST.MF的理解
  11. ab的排列 aa , ab ba,bb
  12. C# 多线程详解
  13. Robot Framework与Web界面自动化测试学习笔记:定位到新窗口
  14. Java Swing界面编程(31)---菜单条:JMenu
  15. 编译安装nginx却requires the PCRE library
  16. 引擎设计跟踪(九.14.3.2) Deferred shading的后续实现和优化
  17. 网络爬虫构造出URL的列表数据
  18. MyBatis(四):mybatis中使用in查询时的注意事项
  19. phantomjs 中如何使用xpath
  20. Json使用示例

热门文章

  1. Hadoop伪集群部署
  2. 线性判别分析(LDA)
  3. 失误1: 把i放到循环体内部,i++失效
  4. JAVA中等待所有线程都执行结束(转2)
  5. Maven实战读书笔记(二):Maven坐标与仓库
  6. 倍增实现LCA
  7. Android 图片设置圆角 方法之二
  8. (十八)python 3 回调函数
  9. STM32定时器的两个小难点
  10. Python利用flask sqlalchemy实现分页效果