1.問題
シンボルの三角形の最初の行に「+」と「-」で構成されるn個のシンボルがあります。将来、シンボルの各行のシンボルは上の行よりも1つ少なくなります。2つの同一の記号は「+」の下にあり、2つの異なる記号は「-」の下にあります。 。同じ数の「+」と「-」が含まれるように、いくつの異なるサイン三角形を計算します。
n = 7のときのシンボル三角形は次のとおりです。
+ + - + - + +
+ - - - - +
- + + + -
- + + -
- + -
- -
+
入力
ラインあたりの正の整数N <= 24、N = 0で終了します。
nとシンボル三角形の数を出力します。
样例输入
15
16
19
20
0
1
2
3
4
5
样例输出
15 1896
16 5160
19 32757
20 59984
二、Solution
方法1:トレント検索(2.8秒)
- 多数の組み合わせがあるため、正当な三角形を作成するのは少し非現実的です。
- 問題を見てみましょう。同じ符号が正で、異なる符号が負であるという定理があるため、次の行のシンボルは前の行のシンボルから計算することもできます。
- したがって、最初の行の配置を列挙するだけで済みます。
- このため、
0^0=0;1^1=0;1^0=1;0^1=1
1を正、0を負とすることができます。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static int[][] g;
static int res;
static int n;
static void op() {
int tot1 = 0, tot2 = 0;
for (int c = 0; c < n; c++) {
if (g[0][c] == 1) tot1++;
else tot2++;
}
for (int i = 1; i < n; i++)
for (int j = 0; j < n-i; j++) {
g[i][j] = g[i-1][j] ^ g[i-1][j+1];
if (g[i][j] == 1) tot1++;
else tot2++;
}
if (tot1 == tot2)
res++;
}
static void dfs(int x) {
if (x == n) {
op();
return;
}
g[0][x] = 1;
dfs(x+1);
g[0][x] = 0;
dfs(x+1);
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
while(true) {
n = sc.nextInt();
if (n == 0)
break;
g = new int[n][n];
dfs(0);
System.out.printf("%d %d\n", n, res);
res = 0;
}
}
}
複雑さの分析
- 時間の複雑さ: 、
- スペースの複雑さ: 、
剪定の最適化:
- タイトルでは、同じ数の記号の三角形を見つける必要があるため、次の場合に検索を早期に終了できます。
- 「+」と「-」の合計が奇数の場合。
- 現在の「+」または「-」はすでに合計の半分を超えており、検索は終了します。
- 現在の数と残りの数の合計は、まだ合計の半分未満です。