伯努利数求自然数幂
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=2−1,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)=en−1n
递推公式: 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+11∑i=0n−1BiCn+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=0∑n−1ik=k+11i=0∑kCk+1iBink+1−i
参考博客: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}
1≤k≤2000,1≤n≤1018)
思路:
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=1∑nik
则 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)k−1=j=0∑k−1Ckjf(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+1−1−∑i=0k−1Ck+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