我正在尝试解决这个问题,但我找不到解决方案:
给出一个由排列成 N 行 M 列的正方形组成的棋盘。这块板的平铺是覆盖它的瓷砖图案。如果满足以下条件,则平铺很有趣:
only tiles of size 1x1 and/or 2x2 are used;
each tile of size 1x1 covers exactly one whole square;
each tile of size 2x2 covers exactly four whole squares;
each square of the board is covered by exactly one tile.
例如,以下图像显示了一块 4 行 3 列的板的一些有趣的平铺:http: //dabi.altervista.org/images/task.img.4x3_tilings_example.gif
如果棋盘上至少存在一个正方形,其中一个棋盘上覆盖有大小为 1x1 的棋子,而另一个棋盘上覆盖着大小为 2x2 的棋子,则棋盘的两个有趣的棋子是不同的。例如,上图中显示的所有平铺都是不同的。
写一个函数
int count_tilings(int N, int M);
即,给定两个整数 N 和 M,返回大小为 N 行和 M 列的板的不同有趣平铺数量的余数模 10,000,007。
假使,假设:
N is an integer within the range [1..1,000,000];
M is an integer within the range [1..7].
例如,给定 N = 4 和 M = 3,函数应该返回 11,因为大小为 4 行和 3 列的板有 11 个不同的有趣平铺:
http://dabi.altervista.org/images/task.img.4x3_tilings_all.gif
对于(4,3),结果是 11,对于(6,5),结果是 1213。我尝试了以下方法,但它不起作用:
static public int count_tilings ( int N,int M ) {
int result=1;
if ((N==1)||(M==1)) return 1;
result=result+(N-1)*(M-1);
int max_tiling= (int) ((int)(Math.ceil(N/2))*(Math.ceil(M/2)));
System.out.println(max_tiling);
for (int i=2; i<=(max_tiling);i++){
if (N>=2*i){
int n=i+(N-i);
int k=i;
//System.out.println("M-1->"+(M-1) +"i->"+i);
System.out.println("(M-1)^i)->"+(Math.pow((M-1),i)));
System.out.println( "n="+n+ " k="+k);
System.out.println(combinations(n, k));
if (N-i*2>0){
result+= Math.pow((M-1),i)*combinations(n, k);
}else{
result+= Math.pow((M-1),i);
}
}
if (M>=2*i){
int n=i+(M-i);
int k=i;
System.out.println("(N-1)^i)->"+(Math.pow((N-1),i)));
System.out.println( "n="+n+ " k="+k);
System.out.println(combinations(n, k));
if (M-i*2>0){
result+= Math.pow((N-1),i)*combinations(n, k);
}else{
result+= Math.pow((N-1),i);
}
}
}
return result;
}
static long combinations(int n, int k) {
/*binomial coefficient*/
long coeff = 1;
for (int i = n - k + 1; i <= n; i++) {
coeff *= i;
}
for (int i = 1; i <= k; i++) {
coeff /= i;
}
return coeff;
}