题目大意: 求 ∑ i = 1 2 n log 2 ( ∏ j = 1 i l o w b i t ( j ) ) \sum_{i=1}^{2^n}\log_2(\prod_{j=1}^i lowbit(j)) ∑i=12nlog2(∏j=1ilowbit(j))。
废话
这场比赛比较晚打,所以只看了前两题,然后因为这第二题也比较毒瘤,所以做完之后比赛就结束了。
但是令我游戏体验爆炸的是,在我推出正解提交的那一刻,洛谷评测机炸了:(
没错,在两分钟前还没有炸:(
然后我第二题就只有
47
47
47 分的好成绩了。
题解
怎么看都不是绿题的亚子啊qwq
可能是我的做法太不优秀了……
我们先考虑求后面的那一串 ∏ j = 1 i l o w b i t ( j ) \prod_{j=1}^i lowbit(j) ∏j=1ilowbit(j)。
既然有
l
o
w
b
i
t
lowbit
lowbit,那么肯定会想到树状数组嘛,那么我们考虑找找规律什么的,先摆一个树状数组出来:
我们惊奇地发现,对于一个
l
o
w
b
i
t
lowbit
lowbit 为
2
x
2^x
2x 的点,他管理的区间的所有点的
l
o
w
b
i
t
lowbit
lowbit 的积恰好就是
2
2
x
−
1
2^{2^x-1}
22x−1。比如说绿色点,它的
l
o
w
b
i
t
lowbit
lowbit 是
2
2
2^2
22,然后他管理的区间的
l
o
w
b
i
t
lowbit
lowbit 之积就是
2
3
2^3
23。
然后会发现,这个证明其实也很简单,我们设 f i f_i fi 表示 l o w b i t lowbit lowbit 为 2 i 2^i 2i 的节点管理区间内的 l o w b i t lowbit lowbit 之积。那么可以得到 f i = 2 f i − 1 2 f_i=2f_{i-1}^2 fi=2fi−12,以上图中绿色节点往蓝色节点转移为例,会发现其实绿色节点管理的 1 1 1 ~ 3 3 3 区间和蓝色节点管理的 5 5 5 ~ 7 7 7 区间是一样的,不同的只有蓝色节点比绿色节点的 l o w b i t lowbit lowbit 要大一倍,所以蓝色节点管理的区间等价于将绿色节点管理的区间复制一份,然后将复制的一份中的最后一个节点的 l o w b i t lowbit lowbit 翻一倍,所以转移就是 2 f i − 1 2 2f_{i-1}^2 2fi−12。
因为 f i f_i fi 必然是一个 2 2 2 的幂,我们不妨用 2 c i 2^{c_i} 2ci 来表示它,那么转移方程又可以表示成: 2 c i = 2 c i − 1 × 2 + 1 2^{c_i}=2^{c_{i-1}\times2+1} 2ci=2ci−1×2+1,因为 f 0 = 2 0 f_0=2^0 f0=20,即 c 0 c_0 c0 等于 0 0 0,所以显然有 c i = 2 i − 1 c_i=2^i-1 ci=2i−1。
所以这个
∏
j
=
1
i
l
o
w
b
i
t
(
j
)
\prod_{j=1}^i lowbit(j)
∏j=1ilowbit(j) 我们可以考虑写成像树状数组求前缀和那样的形式:
∏
j
=
1
i
l
o
w
b
i
t
(
j
)
=
∏
k
=
0
p
f
k
[
i
a
n
d
2
k
>
0
]
=
∏
k
=
0
p
2
c
i
[
i
a
n
d
2
k
>
0
]
=
∏
k
=
0
p
2
2
i
−
1
[
i
a
n
d
2
k
>
0
]
\begin{aligned} \prod_{j=1}^i lowbit(j)&=\prod_{k=0}^p f_k[i~and~2^k>0]\\ &=\prod_{k=0}^p 2^{c_i}[i~and~2^k>0]\\ &=\prod_{k=0}^p 2^{2^i-1}[i~and~2^k>0] \end{aligned}
j=1∏ilowbit(j)=k=0∏pfk[i and 2k>0]=k=0∏p2ci[i and 2k>0]=k=0∏p22i−1[i and 2k>0]
其中, a n d and and 是与运算, p p p 是 i i i 的二进制下的位数。
带回去原柿子,得到:
∑
i
=
1
2
n
log
2
(
∏
k
=
0
n
2
2
i
−
1
[
i
a
n
d
2
k
>
0
]
)
=
∑
i
=
1
2
n
∑
k
=
0
n
2
i
−
1
[
i
a
n
d
2
k
>
0
]
\begin{aligned} &\sum_{i=1}^{2^n}\log_2(\prod_{k=0}^n 2^{2^i-1}[i~and~2^k>0])\\ &=\sum_{i=1}^{2^n}\sum_{k=0}^n 2^i-1[i~and~2^k>0] \end{aligned}
i=1∑2nlog2(k=0∏n22i−1[i and 2k>0])=i=1∑2nk=0∑n2i−1[i and 2k>0]
然而,现在还是不怎么可做,内外层两个循环我们半个都枚举不了……
但是里面的循环的上限是
n
n
n,比较小,我们考虑把它提出来:
∑
k
=
0
n
∑
i
=
1
2
n
2
i
−
1
[
i
a
n
d
2
k
>
0
]
\sum_{k=0}^n \sum_{i=1}^{2^n}2^i-1[i~and~2^k>0]
k=0∑ni=1∑2n2i−1[i and 2k>0]
那么现在就是考虑 1 1 1 ~ 2 n 2^n 2n 这些数在每一个二进制位上的贡献。
考虑到在同一位上的贡献其实都是一样的,所以我们只需要考虑每一位上有多少个数不为 0 0 0。
依然考虑推柿子:设 f ( i ) f(i) f(i) 表示区间 1 1 1 ~ 2 i − 1 2^i-1 2i−1 中所有数的贡献和。
那么 f ( i ) f(i) f(i) 转移到 f ( i + 1 ) f(i+1) f(i+1),相当于多了 2 i 2^i 2i ~ 2 i + 1 − 1 2^{i+1}-1 2i+1−1 这些数,然而我们发现一个奇妙的规律: 2 i + 1 2^i+1 2i+1 ~ 2 i + 1 − 1 2^{i+1}-1 2i+1−1 这些数相当于 1 1 1 ~ 2 i − 1 2^i-1 2i−1 这些数每个数加上 2 i 2^i 2i。所以这些数的贡献等于 f ( i ) + ( 2 i + 1 − 1 − 2 i − 1 + 1 ) × ( 2 i − 1 ) = f ( i ) + ( 2 i − 1 ) 2 f(i)+(2^{i+1}-1-2^i-1+1)\times (2^i-1)=f(i)+(2^i-1)^2 f(i)+(2i+1−1−2i−1+1)×(2i−1)=f(i)+(2i−1)2。
最后把
2
i
2^i
2i 这个数算上,它的贡献是
2
i
−
1
2^i-1
2i−1,所以递推式为:
f
(
i
+
1
)
=
f
(
i
)
+
f
(
i
)
+
(
2
i
−
1
)
2
+
2
i
−
1
=
2
f
(
i
)
+
(
2
i
−
1
)
×
2
i
=
2
f
(
i
)
+
2
2
i
−
2
i
=
2
f
(
i
)
+
4
i
−
2
i
\begin{aligned} f(i+1)&=f(i)+f(i)+(2^i-1)^2+2^i-1\\ &=2f(i)+(2^i-1)\times 2^i\\ &=2f(i)+2^{2i}-2^i\\ &=2f(i)+4^i-2^i\\ \end{aligned}
f(i+1)=f(i)+f(i)+(2i−1)2+2i−1=2f(i)+(2i−1)×2i=2f(i)+22i−2i=2f(i)+4i−2i
即:
f
(
i
)
=
2
f
(
i
−
1
)
+
4
i
−
1
−
2
i
−
1
f(i)=2f(i-1)+4^{i-1}-2^{i-1}
f(i)=2f(i−1)+4i−1−2i−1
其中,根据上面的定义,显然有 f ( 1 ) = 0 f(1)=0 f(1)=0。
所以最后的答案就是 f ( n ) + 2 n − 1 f(n)+2^n-1 f(n)+2n−1,因为 f ( n ) f(n) f(n) 只考虑了 1 1 1 ~ 2 n − 1 2^n-1 2n−1 的贡献,最后还要加上 2 n 2^n 2n 的贡献。那么现在已经得到一个 O ( n ) O(n) O(n) 的 50 50 50 分做法了。
但是我们当然要追求 100 100 100 分,所以考虑求这个递推式的通项公式。
接下来的内容可能引起不适,请务必保证你学过OGF。
接下来我们考虑用生成函数来求通项公式:设 F ( x ) = ∑ i = 1 f ( i ) x i F(x)=\sum_{i=1} f(i)x^i F(x)=∑i=1f(i)xi。
因为没有第 0 0 0 项比较麻烦,我们考虑将 F ( x ) F(x) F(x) 的系数整体左移一位,也就是: F ( x ) = ∑ i = 0 f ( i + 1 ) x i F(x)=\sum_{i=0}f(i+1)x_i F(x)=∑i=0f(i+1)xi。
整体左移一位之后, f f f 的递推式变成 f ( i ) = 2 f ( i − 1 ) + 4 i − 2 i f(i)=2f(i-1)+4^i-2^i f(i)=2f(i−1)+4i−2i,其中 f ( 0 ) = 0 f(0)=0 f(0)=0。
那么根据递推式,我们可以得到:
F
=
2
F
x
+
1
1
−
4
x
−
1
1
−
2
x
F
(
1
−
2
x
)
=
1
1
−
4
x
−
1
1
−
2
x
F
=
1
(
1
−
4
x
)
(
1
−
2
x
)
−
1
(
1
−
2
x
)
2
\begin{aligned} F&=2Fx+\frac 1 {1-4x}-\frac 1 {1-2x}\\ F(1-2x)&=\frac 1 {1-4x}-\frac 1 {1-2x}\\ F&=\frac 1 {(1-4x)(1-2x)}-\frac 1 {(1-2x)^2}\\ \end{aligned}
FF(1−2x)F=2Fx+1−4x1−1−2x1=1−4x1−1−2x1=(1−4x)(1−2x)1−(1−2x)21
发现里面的 1 ( 1 − 4 x ) ( 1 − 2 x ) \frac 1 {(1-4x)(1-2x)} (1−4x)(1−2x)1 无法展开,于是考虑裂项。
设
A
1
−
a
x
+
B
1
−
b
x
=
1
(
1
−
4
x
)
(
1
−
2
x
)
\frac A {1-ax}+\frac B {1-bx}=\frac 1 {(1-4x)(1-2x)}
1−axA+1−bxB=(1−4x)(1−2x)1,那么有:
A
−
b
x
A
+
B
−
a
x
B
(
1
−
a
x
)
(
1
−
b
x
)
=
1
(
1
−
4
x
)
(
1
−
2
x
)
\frac {A-bxA+B-axB} {(1-ax)(1-bx)}=\frac 1 {(1-4x)(1-2x)}
(1−ax)(1−bx)A−bxA+B−axB=(1−4x)(1−2x)1
那么根据这两个柿子的分母,显然有:
{
a
=
4
b
=
2
\begin{cases} a=4\\ b=2 \end{cases}
{a=4b=2
带入到分子中,有:
A
−
2
x
A
+
B
−
4
x
B
=
1
(
A
+
B
)
−
(
2
A
+
4
B
)
x
=
1
\begin{aligned} A-2xA+B-4xB&=1\\ (A+B)-(2A+4B)x&=1 \end{aligned}
A−2xA+B−4xB(A+B)−(2A+4B)x=1=1
那么可以列出方程:
{
A
+
B
=
1
2
A
+
4
B
=
0
\begin{cases} A+B=1\\ 2A+4B=0 \end{cases}
{A+B=12A+4B=0
解得:
{
A
=
2
B
=
−
1
\begin{cases} A=2\\ B=-1 \end{cases}
{A=2B=−1
带回去有:
F
=
2
1
−
4
x
−
1
1
−
2
x
−
1
(
1
−
2
x
)
2
F=\frac 2 {1-4x}-\frac 1 {1-2x}-\frac 1 {(1-2x)^2}
F=1−4x2−1−2x1−(1−2x)21
大力展开,有:
∑
i
=
0
(
2
×
4
i
−
2
i
−
C
i
+
2
−
1
2
−
1
2
i
)
x
i
=
∑
i
=
0
(
2
×
4
i
−
2
i
−
(
i
+
1
)
2
i
)
x
i
\begin{aligned} &\sum_{i=0} (2\times 4^i-2^i-C_{i+2-1}^{2-1}2^i)x^i\\ &=\sum_{i=0} (2\times 4^i-2^i-(i+1)2^i)x^i \end{aligned}
i=0∑(2×4i−2i−Ci+2−12−12i)xi=i=0∑(2×4i−2i−(i+1)2i)xi
因为我们一开始将系数整体左移了一位,所以我们现在需要的是
x
n
−
1
x^{n-1}
xn−1 项的系数而不是
x
n
x^n
xn 的系数,所以答案为:
2
×
4
n
−
1
−
2
n
−
1
−
n
2
n
−
1
+
2
n
−
1
2\times 4^{n-1}-2^{n-1}-n2^{n-1}+2^n-1
2×4n−1−2n−1−n2n−1+2n−1
代码如下(需要注意取模):
#include <cstdio>
#include <cstring>
#define mod 1000000007
#define ll long long
ll n;
ll ksm(ll x,ll y)
{
ll re=1,tot=x;
while(y)
{
if(y&1)re=re*tot%mod;
tot=tot*tot%mod;
y>>=1;
}
return re;
}
int main()
{
scanf("%lld",&n);n--;
printf("%lld",(((2*ksm(4,n)%mod-ksm(2,n)+mod)%mod-(n+1)%mod*ksm(2,n)%mod+mod)%mod+ksm(2,n+1)-1+mod)%mod);
}