Description
求
∑i=1nimmi\sum_{i=1}^{n}i^mm^ii=1∑nimmi
Input
共一行包括两个正整数N和M。
Output
共一行为所求表达式的值对10^9+7取模的值。
Sample Input
5 3
Sample Output
36363
HINT
1<=N<=10^9,1<=M<=1000
题解
好高妙啊
我这种一看就只会拆斯特林数的sb没活路了啊
我们发现mmm很小,又是一个m2m^2m2可过的玩意我就想到拆斯特林数了听说可以猜想递推
递推当然递推mmm啦,根据题解我们递推在次幂的那个玩意
对于f[0]f[0]f[0],他是个等比数列,直接做就好了
然后我们开始拓展
f[k]∗m=∑i=1nik∗mi+1f[k]*m=\sum_{i=1}^n i^k*m^{i+1}f[k]∗m=i=1∑nik∗mi+1
类似等比数列的,我们减去自己尝试开始化简
f[k]∗(m−1)=∑i=1nik∗mi+1−∑i=1nik−mif[k]*(m-1)=\sum_{i=1}^n i^k*m^{i+1}-\sum_{i=1}^n i^k-m^if[k]∗(m−1)=i=1∑nik∗mi+1−i=1∑nik−mi
=∑i=2n+1(i−1)k∗mi−∑i=1nik∗mi=\sum_{i=2}^{n+1}(i-1)^k*m^i-\sum_{i=1}^n i^k*m^i=i=2∑n+1(i−1)k∗mi−i=1∑nik∗mi
=nk∗mn+1+∑i=1nmi∗[(i−1)k−ik]=n^k*m^{n+1}+\sum_{i=1}^{n}m^i*[(i-1)^k-i^k]=nk∗mn+1+i=1∑nmi∗[(i−1)k−ik]
后面二项式展开得到
=nk∗mn+1+∑i=1nmi∗(∑j=0kij∗(−1)k−j∗Ckj−ik)=n^k*m^{n+1}+\sum_{i=1}^{n}m^i*(\sum_{j=0}^{k}i^j*(-1)^{k-j}*C_k^j-i^k)=nk∗mn+1+i=1∑nmi∗(j=0∑kij∗(−1)k−j∗Ckj−ik)
=nk∗mn+1+∑i=1nmi∗∑j=0k−1ij∗(−1)k−j∗Ckj=n^k*m^{n+1}+\sum_{i=1}^{n}m^i*\sum_{j=0}^{k-1}i^j*(-1)^{k-j}*C_k^j=nk∗mn+1+i=1∑nmi∗j=0∑k−1ij∗(−1)k−j∗Ckj
套路地交换求和次序
=nk∗mn+1+∑j=0k−1(−1)k−j∗Ckj∗∑i=1nmi∗ij=n^k*m^{n+1}+\sum_{j=0}^{k-1}(-1)^{k-j}*C_k^j*\sum_{i=1}^{n}m^i*i^j=nk∗mn+1+j=0∑k−1(−1)k−j∗Ckj∗i=1∑nmi∗ij
注意到后面是我们fff的定义式
所以递推有
f[k]=nk∗mn+1+∑j=0k−1(−1)k−j∗Ckj∗f[j]m−1f[k]=\frac{n^k*m^{n+1}+\sum_{j=0}^{k-1}(-1)^{k-j}*C_k^j*f[j]}{m-1}f[k]=m−1nk∗mn+1+∑j=0k−1(−1)k−j∗Ckj∗f[j]
优美的m2m^2m2
有时候
推推递推式会使得题目更加优美…
似乎还有O(m)O(m)O(m)的神仙做法?咕了咕了
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int stack[20];
inline void write(int x)
{
if(x<0){putchar('-');x=-x;}
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int MAXM=1005;
const int mod=1e9+7;
int pow_mod(int a,int b)
{
int ret=1;
while(b)
{
if(b&1)ret=1LL*ret*a%mod;
a=1LL*a*a%mod;b>>=1;
}
return ret;
}
int n,m;
int f[MAXM];
int C[MAXM][MAXM];
void ad(int &x,int y){x+=y;if(x>=mod)x-=mod;}
void dl(int &x,int y){x-=y;if(x<0)x+=mod;}
int main()
{
n=read();m=read();
if(m==1)pr2(1LL*n*(n+1)/2%mod);
else
{
for(int i=0;i<MAXM;i++)
{
C[i][0]=1;
for(int j=1;j<MAXM;j++)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
int inv=pow_mod(m-1,mod-2),pw=pow_mod(m,n+1);
f[0]=1LL*m*(pow_mod(m,n)-1)%mod*inv%mod;
for(int i=1;i<=m;i++)
{
pw=1LL*pw*n%mod;
f[i]=pw;
for(int j=0;j<i;j++)
{
if((i-j)&1)dl(f[i],1LL*C[i][j]*f[j]%mod);
else ad(f[i],1LL*C[i][j]*f[j]%mod);
}
f[i]=1LL*f[i]*inv%mod;
}
pr2(f[m]);
}
return 0;
}

本文介绍了一种利用斯特林数和递推公式高效计算特定幂级数求和的方法,适用于参数规模较大的情况,并给出了具体的算法实现。
261

被折叠的 条评论
为什么被折叠?



