题目大意
设 $x=10^{100}$,在数轴上有 $n$ 个点,第 $i$ 个点的坐标为 $x^i$,每次可以将一个点 $A$ 变为关于点 $B$ 的对称点,并把 $B$ 删除,进行 $n-1$ 次这样的操作,问最后能得到多少种不同的坐标。
$n \le 50$
去看了官方的题解,这里给出官方的 $O(n^4)$ 做法和比较完整的证明。
思路
首先,$x$ 特别大,我们可以直接把每个 $x^i$ 看作是互相独立的。$A$ 关于 $B$ 的对称点实际上就是 $2B-A$。
首先观察可以发现,得到的所有数肯定都是长成 $\sum 2^a(-1)^bx^i$ 的形式。
举个例子,比如最后我们得到了 $2x^1+2x^2+x^3-4x^4$,那么我们发现其实只需要把点的顺序调换一下,就可以得到另外一种结果,比如 $2x^1+2x^3+x^2-4x^4$。
所以我们其实只关心最后得到的系数的集合。上面的例子中,我们只关心最后得到的系数集合 ${1, 2, 2, -4}$。
我们寻找这样的系数集合 $A$ 都有什么性质:
-
$\forall i\in A,\, \exists j,\, \rvert i\lvert=2^j$,即集合中每个元素的绝对值都是 $2$ 的次幂。
证明:考虑对称的过程 $2B-A$,那么实际上每个数就是被乘上了若干个 $2$。
-
$\sum_{i\in A}i=1$,即集合中元素的和为 $1$。
证明:考虑归纳法证明。
首先初始值 ${1}$ 的和为 $1$。
若 $A,B$ 集合均满足以上条件,那么新得到的集合 $2B-A$ 的和为 $2 \times 1 - 1 = 1$,得证。
-
若 $2^i$ 或 $-2^i$ 属于 $A$,那么 $2^{i-1}$ 或 $-2^{i-1}$ 也属于 $A$。
证明:同样归纳法证明,如果 $A$ 包含的指数范围为 $[0,a]$, $B$ 包含的指数范围为 $[0,b]$,那么易证 $2B-A$ 包含的指数范围为 $[0,\max(a,b+1)]$。
-
$2^0$ 和 $-2^0$ 中有一个且仅有一个属于 $A$。
证明:归纳法,首先 $2^0,-2^0$ 都不属于 $2B$,而 $A$ 中有 $2^0,-2^0$ 中的其中一个,所以 $2B-A$ 中有且仅有 $2^0,-2^0$ 中的一个。
但是这些性质都还只是必要条件,并不充分。我们有一个充要条件如下:
对于每一个 $i>1$,存在一种将 $A$ 中的所有 $\pm 2^i$ 元素前的正负号进行修改的方案,使得 $\sum_{\rvert x\lvert=2^j,j\in[0,i]}x=1$(即所有指数小于等于 $i$ 的数的和为 $1$)
证明:
-
必要性:
归纳法。
然后对于每一个 $i>1$,将 $B$ 集合中的 $2^{i-1}$ 元素重标正负号后,得到指数范围在 $[0,i-1]$ 内的数的和为 $1$,并将 $A$ 集合中的 $2^i$ 元素重标正负号后,得到指数范围在 $[0,i]$ 内的数的和为 $1$。
那么 $2B$ 的指数范围就是 $[1,i]$,且 $2^i$ 的正负号被重标,那么 $2B-A$ 就也符合上述性质。
对于 $i=1$,根据性质 $4$,一定可以进行重标正负号使得和为 $1$。
-
充分性:
我们想办法构造出一种方案,使得 $C$ 集合能够被分为 $2B-A$,并且 $A,B,C$ 集合均满足以上的所有性质,即可证明充分性。
首先假设 $-2^0 \in C$。
设 $k$ 为最小的正整数使得 $2^k\in C$。如果对于指数范围在 $[1,k-1]$ 内的所有数都出现了大于等于两次,我们可以构造 $B={-2^0,-2^1,\cdots,-2^{k-2},2^{k-1}}$,这样 $2B={-2^1,-2^2,\cdots,-2^{k-1},2^k}$,我们从 $C$ 集合中刨除掉这些元素,再将元素取反,就得到了 $A$ 集合。
首先可以发现 $B$ 集合满足以上的所有性质,并且 $A$ 集合满足以上的 $4$ 条基本性质。
下面是 $A$ 集合满足性质 $5$ 的证明:
首先对于所有的 $i\le k$,$C$ 集合中的 $\pm2^i$ 在重标正负号后,$2^i$ 的个数一定大于 $-2^i$ 的个数,否则和 $<0$,不满足性质 $5$。
那么在重标正负号的结果中,一定存在一个 $2^i$。我们将这个 $2^i$ 分配给 $B$ 集合,将剩下的分配给 $A$ 集合,那么可以证明 $i\le k$ 的时候性质 $5$ 是成立的。
对于 $i > k$,$C$ 集合重标正负号的结果都分配给了 $A$,因为 $C$ 集合的和为 $1$,$B$ 集合的和也为 $1$,那么 $A$ 集合的和肯定也为 $2\times 1 - 1 = 1$,所以也是成立的。
综上,这样构造出来的 $A$ 集合是满足性质 $5$ 的。
如果对于指数范围在 $[1,k-1]$ 内,存在一个数只出现了一次,那么我们发现再按照上面的方式分配,会导致得到的 $A$ 集合不满足性质 $3$。
那么我们记最小的只出现了一次的指数为 $j$。如果 $j=1$,那么我们可以令 $A={2^0}$,并且 $B$ 为剩下的数除以 $2$。对于 $C$ 的每一个前缀和,将它减去第一个元素 $-2^0$ 再除以 $2$ 也等于 $1$,所以 $B$ 集合也是符合性质 $5$ 的。
如果 $j>1$,那么指数范围在 $[0,j-1]$ 内的数的和的最大值应该为 $-2^0+2(-2^1-2^2-\cdots -2^{j-1})=-2^{j+1}+3$,发现这个数永远小于 $-2^j$,那么无论如何修改 $2^j$ 前面的正负号都无法使得前缀和等于 $1$,所以是不存在 $j>1$ 的情况的。
于是我们证明了性质 $5$ 是一个充要条件。
于是,我们只需要统计满足以上五个条件的集合数有多少种即可。
设 $f_{i,j}$ 表示已经放了 $i$ 个元素,并且这些元素的和为 $1+jV$,其中 $V$ 为现在要放的 $2$ 的次幂是多少。
那么我们枚举选了 $a$ 个 $V$,选了 $b$ 个 $-V$,那么元素的和就变为了 $1+(j+a-b)V$。因为下一个填的数就要比现在的数乘 $2$,所以 $f_{i,j}$ 转移到 $f_{i+a+b,\frac{j+a-b}{2}}$。
我们需要满足将这些数任意标正负号之后,和为 $1$,那么我们只需要满足 $j \equiv a+b \pmod 2$ 且 $a+b\ge \rvert j\lvert$ 即可。
然后考虑对这个系数集合分配原来的 $x^i$,这个就是多重组合数的形式($\frac{n!}{\prod a!}$),我们可以把 $\frac{1}{\prod a!}$ 的部分拆到转移上,也就是 $f_{i,j} \times \frac{1}{a!b!}\rightarrow f_{i+a+b,\frac{j+a-b}{2}}$。
初始状态为 $f_{0,-1}=1$,答案为 $n!f_{n,0}$。
需要注意,为了满足性质 $4$,需要特殊判断一下,当 $i=0$ 时,必须满足 $a+b=1$ 时才可以转移。
Code
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 55, P = 1000000007;
int f[MAXN][MAXN << 1];
int n;
int fac[MAXN], inv[MAXN];
int qpow(int a, int b) {
int ans = 1;
while (b) {
if (b & 1) ans = 1ll * ans * a % P;
a = 1ll * a * a % P;
b >>= 1;
}
return ans;
}
int main() {
scanf("%d", &n);
f[0][MAXN + -1] = 1;
fac[0] = 1;
for (int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % P;
inv[n] = qpow(fac[n], P - 2);
for (int i = n; i >= 1; i--) inv[i - 1] = 1ll * inv[i] * i % P;
for (int i = 0; i < n; i++) {
for (int j = -n; j <= n; j++) if (f[i][j + MAXN]) {
for (int a = 0; a <= n; a++) {
for (int b = 0; i + a + b <= n; b++) if ((a || b) && ((j + a + b) % 2 == 0) && a + b >= abs(j)) {
if (i == 0 && a + b != 1) continue;
f[i + a + b][(j + a - b) / 2 + MAXN] = (f[i + a + b][(j + a - b) / 2 + MAXN]
+ 1ll * f[i][j + MAXN] * inv[a] % P * inv[b]) % P;
}
}
}
}
printf("%lld\n", 1ll * f[n][MAXN + 0] * fac[n] % P);
return 0;
}