自然数幂和

伯努利数求自然数幂

B 0 = 1 , B 1 = − 1 2 , B 2 = 1 6 , B 3 = 0 , B 4 = 1 30 B_0=1,B_1=\frac {−1}2,B_2=\frac 16,B_3=0,B_4=\frac 1{30} B0=1,B1=21,B2=61,B3=0,B4=301

公式: ∑ i = 0 n B i C n + 1 i = 0 \sum_{i=0}^nB_iC_{n+1}^i=0 i=0nBiCn+1i=0,配合 B 0 = 1 B_0=1 B0=1,可以递推计算

通项公式: B ( n ) = n e n − 1 B(n)=\frac {n}{e^n-1} B(n)=en1n

递推公式: B ( n ) = − 1 n + 1 ∑ i = 0 n − 1 B i C n + 1 i B(n)=- \frac 1{n+1} \sum_{i=0}^{n-1}B_i C_{n+1}^i B(n)=n+11i=0n1BiCn+1i,时间复杂度 O ( n 2 ) O(n^2) O(n2)

求自然数幂和的公式:
S k ( n ) = ∑ i = 0 n − 1 i k = 1 k + 1 ∑ i = 0 k C k + 1 i B i n k + 1 − i S_k(n)=\sum_{i=0}^{n-1}i^k=\frac 1{k+1}\sum_{i=0}^kC_{k+1}^i B_i n^{k+1-i} Sk(n)=i=0n1ik=k+11i=0kCk+1iBink+1i
参考博客:https://www.cnblogs.com/cjyyb/p/9268527.html
https://www.cnblogs.com/bztMinamoto/p/10534777.html

1228 序列求和

题意:给定n、k,求 ∑ i = 1 n i k \sum_{i=1}^{n}i^k i=1nik,对1e9+7 取模 ( 1 ≤ k ≤ 2000 , 1 ≤ n ≤ 1 0 18 1\le k\le 2000,1\le n\le 10^{18} 1k2000,1n1018)
思路 O ( k 2 ) O(k^2) O(k2)预处理伯努利数,然后再 O ( k ) O(k) O(k)求自然数幂的前缀和

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;

const int N=2010;
int B[N+10];
int finv[N+10],fac[N+10];

int qpow(ll base,int n,int mod)
{
	base%=mod;
	int ret=1;
	while(n)
	{
		if(n&1)
			ret=1ll*ret*base%mod;
		base=1ll*base*base%mod;
		n>>=1;
	}
	return ret;
}

int C(int n,int m)
{
	return 1ll*fac[n]*finv[m]%mod*finv[n-m]%mod;
}

void init()
{
	fac[0]=fac[1]=1;
	for(int i=2;i<=N;++i)
		fac[i]=1ll*fac[i-1]*i%mod;
	finv[N]=qpow(fac[N],mod-2,mod);
	for(int i=N-1;i>=0;--i)
		finv[i]=1ll*finv[i+1]*(i+1)%mod;
	
	B[0]=1;
	for(int n=1;n<=N;++n)
	{
		ll ans=0;
		for(int i=0;i<=n-1;++i)
			ans=(ans+1ll*B[i]*C(n+1,i)%mod)%mod;
		ans=mod-1ll*ans*qpow(n+1,mod-2,mod)%mod;
		B[n]=ans%mod;		
	}
}

ll solve(ll n,int k)
{
	ll ans=0;
	for(int i=0;i<=k;++i)
		ans=(ans+1ll*C(k+1,i)*B[i]%mod*qpow(n+1,k+1-i,mod)%mod)%mod;
	ans=ans*qpow(k+1,mod-2,mod)%mod;
	return ans;
}

int main()
{
	init();	
	int t;
	scanf("%d",&t);
	while(t--)
	{
		ll n,k;
		scanf("%lld %lld",&n,&k);
		printf("%lld\n",solve(n,k));
	}
	return 0;
}

差分求自然数幂

f ( k ) = ∑ i = 1 n i k f(k)=\sum_{i=1}^n i^k f(k)=i=1nik

f ( k + 1 ) − f ( k ) = ( n + 1 ) k − 1 = ∑ j = 0 k − 1 C k j f ( j ) f(k+1)-f(k)=(n+1)^k-1=\sum_{j=0}^{k-1}C_k^jf(j) f(k+1)f(k)=(n+1)k1=j=0k1Ckjf(j)

最终可得 f ( k ) = ( n + 1 ) k + 1 − 1 − ∑ i = 0 k − 1 C k + 1 i f ( j ) k + 1 f(k)=\frac {(n+1)^{k+1}-1-\sum_{i=0}^{k-1}C_{k+1}^if(j)}{k+1} f(k)=k+1(n+1)k+11i=0k1Ck+1if(j)

可以 O ( k 2 ) O(k^2) O(k2)预处理, O ( 1 ) O(1) O(1)查询

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;

int t;
const int N=2000;
int f[N+10];
int finv[N+10],fac[N+10];

int qpow(int base,int n,int mod)
{
	int ret=1;
	while(n)
	{
		if(n&1)
			ret=1ll*ret*base%mod;
		base=1ll*base*base%mod;
		n>>=1;
	}
	return ret;
}

int C(int n,int m)
{
	return 1ll*fac[n]*finv[m]%mod*finv[n-m]%mod;
}

void init(int n,int K)
{
	fac[0]=fac[1]=1;
	for(int i=2;i<=N;++i)
		fac[i]=1ll*fac[i-1]*i%mod;
	finv[N]=qpow(fac[N],mod-2,mod);
	for(int i=N-1;i>=0;--i)
		finv[i]=1ll*finv[i+1]*(i+1)%mod;
	
	f[0]=n;
	f[1]=1ll*(1+n)*n/2%mod;
	for(int k=2;k<=K;++k)
	{
		ll ans=qpow(n+1,k+1,mod)-1;
		ll tmp=0;
		for(int j=0;j<=k-1;++j)
			tmp=(tmp+1ll*C(k+1,j)*f[j]%mod)%mod;
		ans=(ans-tmp+mod)%mod;
		tmp=qpow(k+1,mod-2,mod);
		ans=ans*tmp%mod;
		f[k]=ans;		
	}
}

int main()
{
	int n,k;
	scanf("%d%d",&n,&k);
	init(n,k);
	printf("%d\n",f[k]);	
	return 0;
}

自然数幂参考博客:https://blog.csdn.net/doyouseeman/article/details/50826293

第二类斯特林数求自然数幂:https://www.cnblogs.com/eztjy/p/9511715.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值