- 题目来源:BZOJ4475
- 一道很久以前做过的题,今天又看到了觉得挺好的就记下来。
- 首先,我们可以对每个元素分开考虑,因为我们可以把子集的限制转化为元素的限制:
A
i
,
j
出现元素
x
⇒
A
i
−
1
,
j
和
A
i
,
j
−
1
出现元素
x
A_{i,j}\text{ 出现元素 }x\Rightarrow A_{i-1,j}\text{ 和 }A_{i,j-1}\text{ 出现元素 }x
Ai,j 出现元素 x⇒Ai−1,j 和 Ai,j−1 出现元素 x
- 因此答案可以表示为 a n a^n an 的形式。
- 现在的问题就是如何求出 a a a 的表达式。
- 我们换一个角度考虑,将这个三角形逆时针旋转
90
°
90°
90°,这样它就变成下面这样:
- - 这是一个合法的选取方案,就是说,某个位置若包含这个元素,那么它的左边及下面的所有格子都要包含。
- 我们设 f k f_k fk 表示边长为 k k k 的阶梯状三角形的填数方案数。
- 我们考虑最后一列的填法。
- 枚举最后一列从下到上选到第 i i i 行的位置, i i i 上面的则不选。
- 那么从下到上前 i i i 行的所有位置都必须选。
- 那么剩余 k − i k-i k−i 行,不受到限制,而最后一列已经确定,则剩余未确定的三角形大小就是 k − i − 1 k-i-1 k−i−1。
- 对于 i = k i=k i=k 特殊考虑即可。
- 递推式即为: f k = ( ∑ i = 0 k − 1 f i ) + 1 f_{k}=(\sum_{i=0}^{k-1}f_{i})+1 fk=(∑i=0k−1fi)+1
- 初值: f 0 = 1 f_{0} = 1 f0=1
- 易得 f k = 2 k f_{k}=2^k fk=2k
- 所以答案即为 2 k n 2^{kn} 2kn。
- 快速幂即可。
#include <bits/stdc++.h>
const int mod = 1e9 + 7;
int n, K;
inline int qpow(int a, int b)
{
int res = 1;
for (; b; b >>= 1, a = 1LL * a * a % mod)
if (b & 1)
res = 1LL * res * a % mod;
return res;
}
int main()
{
scanf("%d%d", &n, &K);
printf("%d\n", qpow(qpow(2, n), K));
return 0;
}