题解:【ABC208F】 Cumulative Sum

题目链接

观察式子得到答案为序列 \(1^k,2^k,\cdots,n^k\)\(m\) 阶前缀和第 \(n\) 项的值。

\(i^k\) 对答案的贡献为 \(f_i\),第 \(j\) 阶前缀和的 \(f_i = g_{j,i}\),那么有递推式子 \(g_{j,i} = g_{j - 1,i} + g_{j,i - 1}\)。这个东西是从 \((i,j)\) 走向 \((0,0)\) 的路径计数,于是 \(f_i\) 对应了 \((1,0) \to (m,n - i)\) 的路径数,根据组合数学这个值是 \(\binom{m - 1 + n - i}{m - 1}\)。由此得到答案式子:

\[\begin{aligned} &\sum_{i = 0}^n \binom{m - 1 + n - i}{m - 1} i^k \\ =&\sum_{i = 0}^n \dfrac{(m - 1 + n - i)!}{(m - 1)!(n - i)!} i^k \end{aligned} \]

以下多项式均为关于 \(i\):前缀和是 \(1\) 次多项式,\(i^k\)\(k\) 次多项式;\((m - 1 + n - i)!\)\(m - 1 + n - i\) 次多项式,\((n - i)!\)\(n - i\) 次多项式,\((m - 1)!\) 则是常数,这个分数约出来是个 \(m - 1\) 次多项式。综上所述,这个式子是一个 \(k + m\) 次多项式。使用拉格朗日插值带入 \(k + m + 1\) 个点值即可得出多项式。加上求逆元和前缀和啥的,总的时间复杂度是 \(\mathcal O(k \log k + (k + m)m)\)。代码实现使用的递推求逆元。

#include<bits/stdc++.h>
#define ld long double
#define ui unsigned int
#define ull unsigned long long
#define int long long
#define eb emplace_back
#define pb pop_back
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define power(x) ((x)*(x))
#define gcd(x,y) __gcd(x,y)
#define lcm(x,y) (x*y/gcd(x,y))
#define lg(x,y)  __lg(x,y)
using namespace std;

template<typename T=int> inline T read()
{
    T s=0,w=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-') w=-1; c=getchar();}
    while(isdigit(c)) s=(s<<1)+(s<<3)+(c^48),c=getchar();
    return s*w;
}
template<typename T=int> inline void write(T x,char ch)
{
    if(x<0) x=-x,putchar('-');
    static char stk[25]; int top=0;
    do {stk[top++]=x%10+'0',x/=10;} while(x);
    while(top) putchar(stk[--top]);
    putchar(ch);
    return;
}

namespace MyTool
{
    static const int Mod=1e9+7;
    template<typename T> inline void Swp(T &a,T &b) {T t=a;a=b;b=t;}
    template<typename T> inline void cmax(T &a,T b) {a=a>b?a:b;}
    template<typename T> inline void cmin(T &a,T b) {a=a<b?a:b;}
    template<typename T> inline void Madd(T &a,T b) {a=a+b>Mod?a+b-Mod:a+b;}
    template<typename T> inline void Mdel(T &a,T b) {a=a-b<0?a-b+Mod:a-b;}
    template<typename T> inline void Mmul(T &a,T b) {a=a*b%Mod;}
    template<typename T> inline void Mmod(T &a)     {a=(a%Mod+Mod)%Mod;}
    template<typename T> inline T    Cadd(T a,T b)  {return a+b>=Mod?a+b-Mod:a+b;}
    template<typename T> inline T    Cdel(T a,T b)  {return a-b<0?a-b+Mod:a-b;}
    template<typename T> inline T    Cmul(T a,T b)  {return a*b%Mod;}
    template<typename T> inline T    Cmod(T a)      {return (a%Mod+Mod)%Mod;}
    inline int qpow(int a,int b) {int res=1; while(b) {if(b&1) Mmul(res,a); Mmul(a,a); b>>=1;} return res;}
    inline int qmul(int a,int b) {int res=0; while(b) {if(b&1) Madd(res,a); Madd(a,a); b>>=1;} return res;}
    inline int Qpow(int a,int b) {int res=1; while(b) {if(b&1) res=qmul(res,a); a=qmul(a,a); b>>=1;} return res;} 
}
using namespace MyTool;

inline void file()
{
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
    return;
}

bool Mbe;

namespace LgxTpre
{
    static const int MAX=2600010;
    static const int inf=2147483647;
    static const int INF=4557430888798830399;
    static const int mod=1e9+7;
    static const int bas=131;

    int n,m,k,l,ans;
    int a[MAX],fac[MAX],inv[MAX],pre[MAX],suf[MAX];

    inline void lmy_forever()
    {
    	n=read(),m=read(),k=read(),l=m+k+1; Mmod(n);
    	if(!n) return puts("0"),void();
    	for(int i=1;i<=l;++i) a[i]=qpow(i,k);
    	for(int i=1;i<=m;++i) for(int j=1;j<=l;++j) Madd(a[j],a[j-1]);
    	inv[0]=fac[0]=1;           for(int i=1;i<=l;++i) fac[i]=Cmul(fac[i-1],i);
    	inv[l]=qpow(fac[l],Mod-2); for(int i=l-1;i;--i)  inv[i]=Cmul(inv[i+1],i+1);
    	pre[0]=1;                  for(int i=1;i<=l;++i) pre[i]=Cmul(pre[i-1],n-i);
    	suf[l+1]=1;                for(int i=l;i;--i)    suf[i]=Cmul(suf[i+1],n-i);
    	for(int i=1;i<=l;++i) Madd(ans,Cmul(a[i],Cmul(Cmod(Cmul(Cmul(inv[i-1],inv[l-i]),(l-i)&1?-1ll:1ll)),Cmul(pre[i-1],suf[i+1]))));
    	write(ans,'\n');
    }
}

bool Med;

signed main()
{
//  file();
    fprintf(stderr,"%.3lf MB\n",abs(&Med-&Mbe)/1048576.0);
    int Tbe=clock();
    LgxTpre::lmy_forever();
    int Ted=clock();
    cerr<<1e3*(Ted-Tbe)/CLOCKS_PER_SEC<<" ms\n";
    return (0-0);
}
posted @ 2023-05-28 17:40  LgxTpre  阅读(22)  评论(0编辑  收藏  举报