- 注册时间
- 2007-12-27
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 40149
- 在线时间
- 小时
|
楼主 |
发表于 2010-4-1 11:12:12
|
显示全部楼层
另外一种方法我认为更加有效一些,因为使用的内存会更小,可以用于计算更加大的范围的结果,但是实现起来更加麻烦一些,而且我不能像Fans一样,
可以直接将编程工作交给“秘书”,这里就纸上谈兵一把:
我们记$g(n)=f(2n),g(0)=1$,那么我们可以知道
$g(2n)=2g(0)+2g(1)+...+2g(n-1)+g(n)$
$g(2n+1)=2g(0)+2g(1)+...+2g(n-1)+2g(n)$
我们记$n_h=n>>h$,也就是$n_h$是n右移h位,特别的$n_0=n$.而设n的二进制表示为b位,所以$n_b=0$
所以我们知道,如果$n_0$是奇数,那么必然有
$g(n)=2g(0)+2g(1)+...+2g(n_1-1)+2g(n_1)$
而如果$n_0$是偶数,那么必然有
$g(n)=2g(0)+2g(1)+...+2g(n_1-1)+1g(n_1)$
更加一般的,我们假设
$g(n)=u_{n,h}(0)g(0)+u_{n,h}(1)g(1)+...+u_{n,h}(n_{h+1}-1)g(n_{h+1}-1)+c_{n,h}g(n_{h+1})$
其中$u_{n,h}(x)$是一个h次多项式,
我们将右边再次使用上面的基本递推公式得到
$g(n)=$
$u_{n,h}(0)*1*g(0)+$
$u_{n,h}(1)*2*g(0)+$
$u_{n,h}(2)*2*g(0)+u_{n,h}(2)*1*g(1)+$
$...$
$u_{n,h}(n_{h+1}-1)*2*g(0)+....$
$c_{n,h}*2*g(0)+...$
我们现在查看右边$g(0),g(1),...,g(n_{h+2})$的系数可以知道
它们的通常形式是$g(t)$的系数为$u_{n,h}(2t)*1+2*sum_{u=2t+1}^{n_{h+1}-1}u_{n,h}(u)+2*c_{n,h}$
而只有$n_{h+1}$是偶数时,最后一项会例外,它变成$c_{n,h}$
而上面通常形式中第一项是t的h次多项式,那个求和式可以变成t的h+1次多项式,所以总体会变成一个h+1次多项式
也就是说,同前面类似,除了最后一项系数可能例外,其余的系数可以用一个h+1次多项式统一描绘。
所以如果我们一直通过这种方法递推下去,找到$u_{n,b-1}$和$c_{n,b-1}$,那么就可以计算出$g(n)$了。
但是这里还有一个问题,就是里面那个多项式累加求和如何计算的问题,我们当然可以直接使用$sum_{x=t}^s x^h$的求和公式,但是比较复杂
而且会出现分数表示。一个更加好的办法是记
$v_0(x)=1,v_1(x)=x/{1!},v_2(x)={x(x-1)}/{2!},...,v_t(x)={x(x-1)...(x-t+1)}/{t!},...$
然后我们需要事先计算表格M(a,b)使得
$v_s(2x)=sum_{t=0}^s M(s,t)v_t(x)$
这个表格的计算也比较简单,首先,$v_0(2x)=v_0(x)$
其次
$v_{s+1}(2x)=v_s(2x)*{2x-s}/{s+1}=sum_{t=0}^s M(s,t)v_t(x){2x-2t+2t-s}/{s+1}=sum_{t=0}^s ({2(t+1)}/{s+1}M(s,t)v_{t+1}(x)+{2t-s}/{s+1}M(s,t)v_t(x))$
我们可以递推出整个表格M,只是每次计算时会牵涉到一个分母s+1,但是我们知道合并结果以后必然是整数,所以可以计算过程都乘上s+1,最后除去s+1就可以了。
先我们可以设$u_{n,h}(x)=sum_{t=0}^h U_{n,t}*v_t(x)$
我们现在主要需要计算$sum_{u=2t+1}^{n_{h+1}-1}u_{n,h}(u)$
由于$sum_{u=2t+1}^av_s(u)=v_{s+1}(a+1)-v_{s+1}(2t+1)$
所以合并以后每个$g(t)$的系数形式为$sum_s a_s*v_s(2t)+b_s*v_s(2t+1)+c$
这时我们就需要表格M(a,b)将$v_s(2t)$转化为$v_s(t)$的线性组合。而$v_s(2t+1)=v_{s-1}(2t)+v_s(2t)$,于是它也可以通过同一个表格转化
由此我们可以得到$u_{n,h+1}$
这个算法整体时间复杂度也是$O(log^3(n))$此大数乘法运算,内存复杂度看上去同前面算法相同,也是$O(log^2(n))$,但是前面算法中数组T保存的是$2^t$的划分数,是很大的整数,
而这里的表格M中保存的数相对都比较小(不会超过n),所以花费的内存要小很多 |
|