AFOI-19 sum与prod 题解

题目传送门

题目大意: 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))

废话

这场比赛比较晚打,所以只看了前两题,然后因为这第二题也比较毒瘤,所以做完之后比赛就结束了。

但是令我游戏体验爆炸的是,在我推出正解提交的那一刻,洛谷评测机炸了:(

没错,在两分钟前还没有炸:(
在这里插入图片描述
然后我第二题就只有 47 47 的好成绩了。

题解

怎么看都不是绿题的亚子啊qwq

可能是我的做法太不优秀了……

我们先考虑求后面的那一串 j = 1 i l o w b i t ( j ) \prod_{j=1}^i lowbit(j)

既然有 l o w b i t lowbit ,那么肯定会想到树状数组嘛,那么我们考虑找找规律什么的,先摆一个树状数组出来:
在这里插入图片描述
我们惊奇地发现,对于一个 l o w b i t lowbit 2 x 2^x 的点,他管理的区间的所有点的 l o w b i t lowbit 的积恰好就是 2 2 x 1 2^{2^x-1} 。比如说绿色点,它的 l o w b i t lowbit 2 2 2^2 ,然后他管理的区间的 l o w b i t lowbit 之积就是 2 3 2^3

然后会发现,这个证明其实也很简单,我们设 f i f_i 表示 l o w b i t lowbit 2 i 2^i 的节点管理区间内的 l o w b i t lowbit 之积。那么可以得到 f i = 2 f i 1 2 f_i=2f_{i-1}^2 ,以上图中绿色节点往蓝色节点转移为例,会发现其实绿色节点管理的 1 1 ~ 3 3 区间和蓝色节点管理的 5 5 ~ 7 7 区间是一样的,不同的只有蓝色节点比绿色节点的 l o w b i t lowbit 要大一倍,所以蓝色节点管理的区间等价于将绿色节点管理的区间复制一份,然后将复制的一份中的最后一个节点的 l o w b i t lowbit 翻一倍,所以转移就是 2 f i 1 2 2f_{i-1}^2

因为 f i f_i 必然是一个 2 2 的幂,我们不妨用 2 c i 2^{c_i} 来表示它,那么转移方程又可以表示成: 2 c i = 2 c i 1 × 2 + 1 2^{c_i}=2^{c_{i-1}\times2+1} ,因为 f 0 = 2 0 f_0=2^0 ,即 c 0 c_0 等于 0 0 ,所以显然有 c i = 2 i 1 c_i=2^i-1

所以这个 j = 1 i l o w b i t ( j ) \prod_{j=1}^i lowbit(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}

其中, a n d and 运算, p p 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}

然而,现在还是不怎么可做,内外层两个循环我们半个都枚举不了……

但是里面的循环的上限是 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]

那么现在就是考虑 1 1 ~ 2 n 2^n 这些数在每一个二进制位上的贡献。

考虑到在同一位上的贡献其实都是一样的,所以我们只需要考虑每一位上有多少个数不为 0 0

依然考虑推柿子:设 f ( i ) f(i) 表示区间 1 1 ~ 2 i 1 2^i-1 中所有数的贡献和。

那么 f ( i ) f(i) 转移到 f ( i + 1 ) f(i+1) ,相当于多了 2 i 2^i ~ 2 i + 1 1 2^{i+1}-1 这些数,然而我们发现一个奇妙的规律: 2 i + 1 2^i+1 ~ 2 i + 1 1 2^{i+1}-1 这些数相当于 1 1 ~ 2 i 1 2^i-1 这些数每个数加上 2 i 2^i 。所以这些数的贡献等于 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

最后把 2 i 2^i 这个数算上,它的贡献是 2 i 1 2^i-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 ) = 2 f ( i 1 ) + 4 i 1 2 i 1 f(i)=2f(i-1)+4^{i-1}-2^{i-1}

其中,根据上面的定义,显然有 f ( 1 ) = 0 f(1)=0

所以最后的答案就是 f ( n ) + 2 n 1 f(n)+2^n-1 ,因为 f ( n ) f(n) 只考虑了 1 1 ~ 2 n 1 2^n-1 的贡献,最后还要加上 2 n 2^n 的贡献。那么现在已经得到一个 O ( n ) O(n) 50 50 分做法了。

但是我们当然要追求 100 100 分,所以考虑求这个递推式的通项公式。

接下来的内容可能引起不适,请务必保证你学过OGF

接下来我们考虑用生成函数来求通项公式:设 F ( x ) = i = 1 f ( i ) x i F(x)=\sum_{i=1} f(i)x^i

因为没有第 0 0 项比较麻烦,我们考虑将 F ( x ) F(x) 的系数整体左移一位,也就是: F ( x ) = i = 0 f ( i + 1 ) x i F(x)=\sum_{i=0}f(i+1)x_i

整体左移一位之后, f f 的递推式变成 f ( i ) = 2 f ( i 1 ) + 4 i 2 i f(i)=2f(i-1)+4^i-2^i ,其中 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}

发现里面的 1 ( 1 4 x ) ( 1 2 x ) \frac 1 {(1-4x)(1-2x)} 无法展开,于是考虑裂项


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)} ,那么有:
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)}

那么根据这两个柿子的分母,显然有:
{ a = 4 b = 2 \begin{cases} a=4\\ b=2 \end{cases}

带入到分子中,有:
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 + B = 1 2 A + 4 B = 0 \begin{cases} A+B=1\\ 2A+4B=0 \end{cases}

解得:
{ A = 2 B = 1 \begin{cases} A=2\\ B=-1 \end{cases}


带回去有:
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}

大力展开,有:
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}

因为我们一开始将系数整体左移了一位,所以我们现在需要的是 x n 1 x^{n-1} 项的系数而不是 x n x^n 的系数,所以答案为:
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

代码如下(需要注意取模):

#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);
}
发布了234 篇原创文章 · 获赞 100 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/a_forever_dream/article/details/102963750