HDOJ 1812 Count the Tetris
2016-06-27 16:21
507 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1812
这道题我们要用到的是Pólya定理(如果不懂Pólya定理的同学,欢迎观看小编的另一篇博客)。
此题置换的方式一共有8种置换方式,大类可以分为两个大类:旋转和翻折。我们求出每一种置换方式的循环节个数就可以了。
1.旋转:
旋转0度(360度):每一个格子都是到自己的一个循环节,所以循环节个数为n*n。
旋转90度(顺时针):
(1)如果n为偶数,那么每一个格子都可以旋转四次回到自己这里,所以循环个数为(n*n)/4
(2)如果n为奇数,那么除了正中间那个格子都和偶数时一样,但中间那个单独的格子也是一个循环节,所以循环节个数为:(n*n-1)/4+1。
旋转90度(逆时针):同上偶数(n*n)/4 奇数为(n*n-1)/4+1。
旋转180度:
(1)如果n为偶数,那么每一个格子都可以旋转两次回到自己这里,所以循环节个数为(n*n)/2。
(2)如果n为奇数,那么除了正中间那个格子都和偶数时一样,但中间那个单独的格子也是一个循环节,所以循环节个数为:(n*n-1)/2+1。
2.翻折:
沿着中心线翻折(两个方向):
(1)如果n为偶数,那么每一个格子都试翻折两次回到自己这里,所以循环节个数为(n*n)/2。
(2)如果n为奇数,那么除了中间那一列的格子都和偶数时一样,但中间那列格子自己也会有个循环节,所以循环节的个数为:(n*n-n)/2+n。
沿着对角线翻折(两个方向):除了对角线上的格子自己就是一个循环节,其他的格子都是每翻折两次回到自己这里,所以循环节就是(n*n-n)/2+n。
有了这些循环节后,我们就可以直接套Pólya定理公式得到答案了。
PS.此题属于大数据。
import java.util.*;
import java.math.*;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(input.hasNext())
{
int n = input.nextInt();
BigInteger c = input.nextBigInteger();
BigInteger ans = BigInteger.ZERO;
if(n%2 == 0)
{
ans = ans.add(c.pow(n*n));
ans = ans.add(BigInteger.valueOf(2).multiply(c.pow(n*n/4)));
ans = ans.add(BigInteger.valueOf(3).multiply(c.pow(n*n/2)));
ans = ans.add(BigInteger.valueOf(2).multiply(c.pow((n*n-n)/2+n)));
}
else
{
ans = ans.add(c.pow(n*n));
ans = ans.add(BigInteger.valueOf(2).multiply(c.pow((n*n-1)/4+1)));
ans = ans.add(c.pow((n*n-1)/2+1));
ans = ans.add(BigInteger.valueOf(4).multiply(c.pow((n*n-n)/2+n)));
}
ans = ans.divide(BigInteger.valueOf(8));
System.out.println(ans);
}
}
}
这道题我们要用到的是Pólya定理(如果不懂Pólya定理的同学,欢迎观看小编的另一篇博客)。
此题置换的方式一共有8种置换方式,大类可以分为两个大类:旋转和翻折。我们求出每一种置换方式的循环节个数就可以了。
1.旋转:
旋转0度(360度):每一个格子都是到自己的一个循环节,所以循环节个数为n*n。
旋转90度(顺时针):
(1)如果n为偶数,那么每一个格子都可以旋转四次回到自己这里,所以循环个数为(n*n)/4
(2)如果n为奇数,那么除了正中间那个格子都和偶数时一样,但中间那个单独的格子也是一个循环节,所以循环节个数为:(n*n-1)/4+1。
旋转90度(逆时针):同上偶数(n*n)/4 奇数为(n*n-1)/4+1。
旋转180度:
(1)如果n为偶数,那么每一个格子都可以旋转两次回到自己这里,所以循环节个数为(n*n)/2。
(2)如果n为奇数,那么除了正中间那个格子都和偶数时一样,但中间那个单独的格子也是一个循环节,所以循环节个数为:(n*n-1)/2+1。
2.翻折:
沿着中心线翻折(两个方向):
(1)如果n为偶数,那么每一个格子都试翻折两次回到自己这里,所以循环节个数为(n*n)/2。
(2)如果n为奇数,那么除了中间那一列的格子都和偶数时一样,但中间那列格子自己也会有个循环节,所以循环节的个数为:(n*n-n)/2+n。
沿着对角线翻折(两个方向):除了对角线上的格子自己就是一个循环节,其他的格子都是每翻折两次回到自己这里,所以循环节就是(n*n-n)/2+n。
有了这些循环节后,我们就可以直接套Pólya定理公式得到答案了。
PS.此题属于大数据。
import java.util.*;
import java.math.*;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(input.hasNext())
{
int n = input.nextInt();
BigInteger c = input.nextBigInteger();
BigInteger ans = BigInteger.ZERO;
if(n%2 == 0)
{
ans = ans.add(c.pow(n*n));
ans = ans.add(BigInteger.valueOf(2).multiply(c.pow(n*n/4)));
ans = ans.add(BigInteger.valueOf(3).multiply(c.pow(n*n/2)));
ans = ans.add(BigInteger.valueOf(2).multiply(c.pow((n*n-n)/2+n)));
}
else
{
ans = ans.add(c.pow(n*n));
ans = ans.add(BigInteger.valueOf(2).multiply(c.pow((n*n-1)/4+1)));
ans = ans.add(c.pow((n*n-1)/2+1));
ans = ans.add(BigInteger.valueOf(4).multiply(c.pow((n*n-n)/2+n)));
}
ans = ans.divide(BigInteger.valueOf(8));
System.out.println(ans);
}
}
}
相关文章推荐
- POJ1273 Drainage Ditches 【最大流】
- 好长时间没更新了..
- HTML5 canvas画布(五)
- ubuntu 14.04 网络图标消失解决方法 状态栏图标不显示
- 利用GBDT模型构造新特征
- 矩阵及其基本运算
- 1006-F专题四
- Tomcat启动报Error listenerStart错误
- Problem H
- C# TreeView无限目录树实现方法
- C++ 设计与声明原则
- C++中输入输出流及文件流操作笔记
- 宽客人生-读书笔记
- jQuery 中 attr 和 prop 方法的区别
- 瀑布流的加载更多
- AngularJS directive指令
- R.String.xxx
- 截取指定字符前后的指定长度的字符,得到新的字符串
- Java基础之异常Exception---测试(带答案)
- React Native控件之Switch与Picker组件讲解