zoukankan      html  css  js  c++  java
  • cojs 疯狂的求和问题 解题报告

    QAQ 好久不在cojs上出题了

    最近学了点新科技,于是就做成题来分享了

    这道题是要求simga(i^k)

    那么就先说说部分分的算法吧:

    10分:

    直接暴力就可以了,时间复杂度O(nlogk)

    30分:

    我们考虑设S(n)表示1^k+2^k+……+n^k的和

    不难发现S(n+1)=S(n)+(n+1)^k

    由二项式定理得(n+1)^k=sigma( C(k,i)*n^i  )

    构造向量(n^0,n^1,n^2……,n^k,S(n))

    不难根据刚才的式子构造出转移矩阵,之后矩阵乘法+快速幂就可以了

    时间复杂度O(k^3logn)

    60分:

    设S(d)表示0^d+1^d+2^d+……+(n-1)^d的和

    注意到(d+1)^i - d^i = sigma( C(i,j) *d^j )(其中j不等于i)

    如果d的取值为0-(n-1)我们对左式求sigma

    我们得到左式=n^i

    相应的右式经过化简之后得到sigma( C(i,j) * S(j) )( j<i )

    这样C(i,i-1)*S(i-1)=n^i-sigma( C(i,j) *S(j) )( j<i-1 )

    由于S(0)已知,所以我们可以在O(k^2)的时间内递推出结果

    80分:

    我们定义伯努利数为B

    可以得到 sigma(i^k) = sigma( C(k+1,j) * B(k+1-j) * (n+1)^j )/(k+1)

    如果我们可以快速求出伯努利数,那么我们就可以在O(k)时间内算出答案

    我们知道伯努利数的生成函数为x/(e^x-1)

    对e^x做泰勒展开之后上下同时消掉一个x我们可以得到

    伯努利数的多项式的生成函数 1 / (x^i/(i+1)!)

    考虑到分母的多项式是非常容易求出的,而伯努利数的多项式就是这个多项式的逆

    多项式求逆即可,时间复杂度O(klogk),常数巨大

    100分:

    由题面我们其实可以知道sigma(i^k)的通项公式实际上是一个(i+1)次的多项式

    设这个多项式为f

    我们实际上要求的是f(x)也就是某个点的值

    不难在O(klogk)的时间内求出当x=(0->(k+1))的每个点的值

    已知k+2个点值,则可以唯一确定一个k+1次的多项式

    直接代入拉格朗日插值公式即可得到f(n)的值

    注意到直接使用拉格朗日插值公式的时间复杂度是O(k^2)的

    但是由于我们相邻点的x坐标相差为1

    可以通过预处理阶乘和阶乘的逆元做到O(k)的插值出f(n)

    总时间复杂度O(klogk),但是由于log取得是快速幂,所以常数较小

  • 相关阅读:
    旋转数组的最小值
    用堆栈实现队列
    二叉树的重建
    从尾到头打印链表
    实现替换空格
    java获取在各种编码下中文及英文的字符个数
    java定义一个二维数组
    java计算某个坐标是否在范围内
    java调用百度地图API
    map在遍历数据的过程中删除数据不出错
  • 原文地址:https://www.cnblogs.com/joyouth/p/5583541.html
Copyright © 2011-2022 走看看