求自然数幂和

Posted zhgyki

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求自然数幂和相关的知识,希望对你有一定的参考价值。

求自然数幂和,就是一条公式,然后用代码实现;

      公式描述如下:

 

     技术分享图片

 

     可以看出只要我们预处理出每一项,就可以在线性时间内求得自然数的幂和。前面的倒数可以用递推法求逆元

     预处理,组合数也可以预处理,技术分享图片也可以先预处理,现在关键是如何预处理伯努利数。

 

     伯努利数满足条件技术分享图片,且有

 

     技术分享图片

 

     那么继续得到

 

     技术分享图片

 

     这就是伯努利数的递推式,逆元部分同样可以预处理。

代码:

typedef long long ll;
typedef unsigned long long ull;
const ll N=2005;
const ll mod=1e9+7;

ll inv[N],B[N];
ll C[N][N];
ll tmp[N];
ll n,k;

void init()
{
    //预处理组合数
    for(int i=0;i<N;i++)
    {
        C[i][0]=1;
        for(int j=1;j<=i;j++)
            C[i][j]=(C[i-1][j]%mod+C[i-1][j-1]%mod)%mod;
    }
    //预处理逆元
    inv[1]=1;
    for(int i=2;i<N;i++)
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        ;
    // 预处理伯努利数
    B[0]=1;
    for(int i=1;i<N;i++)
    {
        ll ans=0;
        if(i==N-1)break;
        for(int j=0;j<i;j++)
        {
            ans+=C[i+1][j]*B[j];
            ans%=mod;
        }
        ans*=-inv[i+1];
        ans=(ans%mod+mod)%mod;
        B[i]=ans;
    }
}
ll work(ll k)
{
    ll ans=inv[k+1];
    ll sum=0;
    for(int i=1;i<=k+1;i++)
    {
        sum+=C[k+1][i]*tmp[i]%mod*B[k+1-i]%mod;
        sum%=mod;
    }
    ans*=sum;
    ans%=mod;
    return ans;
}
ll sum(ll n,ll k)
{
    if(n<0)return 0;
    n%=mod;
    tmp[0]=1;
    for(int i=1;i<N;i++)
        tmp[i]=tmp[i-1]*(n+1)%mod;
    return work(k);
}

参考博客:https://blog.csdn.net/acdreamers/article/details/38929067

以上是关于求自然数幂和的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2137 submultiple(约数,拉格朗日插值求自然数k次幂和)BZOJ 修复工程

BZOJ 2137 submultiple(约数,拉格朗日插值求自然数k次幂和)BZOJ 修复工程

自然数幂和

自然数幂和[第二类斯特林数求法]

康复计划#3 简单常用的几种计算自然数幂和的方法

求解自然数幂和的若干种方法