浅谈下降幂

公式:

题目

P6620 [省选联考 2020 A 卷] 组合数问题

题解

代码

#include<bits/stdc++.h>
using namespace std;
#define next Nxt
#define last Lst
#define gc getchar
#define int long long
const int N=1005;
int n,m,mod,ans,x,a[N],b[N],c[N],d[N],e[N],s[N][N];
//char buf[1<<21],*p1=buf,*p2=buf;
//inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
inline int read()
{
    int ret=0,f=0;char c=gc();
    while(!isdigit(c)){if(c=='-')f=1;c=gc();}
    while(isdigit(c)){ret=ret*10+c-48;c=gc();}
    if(f)return -ret;return ret;
}
int kuai(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b=b/2;
    }
    return res;
}
int work(int x)
{
    int res=1;
    for(int i=n-x+1;i<=n;i++)res=res*i%mod;
    return res;
}
int work2(int x)
{
    int res=0;
    for(int i=x;i<=m;i++)res=(res+a[i]*s[i][x])%mod;
    return res;
}
signed main()
{
    n=read();x=read();mod=read();m=read();
    for(int i=0;i<=m;i++)a[i]=read();
    for(int i=0;i<=m;i++)e[i]=work(i);
    s[0][0]=1;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
            s[i][j]=(s[i-1][j-1]+s[i-1][j]*j)%mod;
    for(int i=0;i<=m;i++)b[i]=work2(i);
    c[0]=1;
    for(int i=1;i<=m;i++)c[i]=c[i-1]*x%mod;
    for(int i=0;i<=m;i++)d[i]=kuai((x+1)%mod,n-i);
    for(int i=0;i<=m;i++)
        ans=(ans+e[i]*b[i]%mod*c[i]%mod*d[i]%mod)%mod;
    cout<<ans;
    return 0;
}

题目

P6667 [清华集训2016] 如何优雅地求和

题解

出题人毒瘤,是以点值的形式给出,我们要转化为的形式。

这就是多项式插值,我们可以用的拉格朗日插值来解决,具体就是

对于,把当成未知数,求出这个多项式每一项的系数。

代码

#include<bits/stdc++.h>
using namespace std;
#define next Nxt
#define last Lst
//#define gc getchar
//#define int long long
const int N=20005;
const int mod=998244353;
int n,m,ans,len,x,y[N],inv[N],f[N],a[N],b[N],c[N],d[N],e[N],s[2][N];
char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
inline int read()
{
    int ret=0,f=0;char c=gc();
    while(!isdigit(c)){if(c=='-')f=1;c=gc();}
    while(isdigit(c)){ret=ret*10+c-48;c=gc();}
    if(f)return -ret;return ret;
}
int kuai(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)res=1ll*res*a%mod;
        a=1ll*a*a%mod;
        b=b/2;
    }
    return res;
}
int work(int x)
{
    int res=1;
    for(int i=n-x+1;i<=n;i++)res=1ll*res*i%mod;
    return res;
}
void solve(int x)
{
    for(int i=0;i<=len;i++)c[i]=a[i];
    for(int i=len;i;i--)
    {
        b[i-1]=c[i];
        c[i-1]=(c[i-1]+1ll*c[i]*x%mod+mod)%mod;
    }
}
signed main()
{
    n=read();m=read();x=read();
    for(int i=0;i<=m;i++)y[i]=read();
    a[1]=1;
    len=1;
    for(int i=1;i<=m;i++)
    {
        b[0]=0;
        for(int j=0;j<=len;j++)
            b[j+1]=a[j];
        for(int j=0;j<=len;j++)
            b[j]=(b[j]-1ll*a[j]*i%mod+mod)%mod;
        len++;
        for(int j=0;j<=len;j++)a[j]=b[j];
    }
    for(int i=0;i<=m;i++)
    {
        inv[i]=1;
        for(int j=0;j<=m;j++)
            if(i!=j)inv[i]=1ll*inv[i]*(i-j)%mod;
        inv[i]=(inv[i]+mod)%mod;
        inv[i]=kuai(inv[i],mod-2);
    }
    for(int i=0;i<=m;i++)
    {
        solve(i);
        for(int j=0;j<len;j++)
            f[j]=(f[j]+1ll*b[j]*y[i]%mod*inv[i]%mod)%mod;
    }
    for(int i=0;i<=m;i++)a[i]=f[i];
    for(int i=0;i<=m;i++)e[i]=work(i);
    for(int i=0;i<=m;i++)b[i]=0;
    s[0][0]=1;
    b[0]=a[0];
    for(int i=1;i<=m;i++)
    {
        int u=i&1,v=(i-1)&1;
        if(i>1)s[0][0]=0;
        for(int j=1;j<=m;j++)
            s[u][j]=(s[v][j-1]+1ll*s[v][j]*j)%mod;
        for(int j=0;j<=i;j++)b[j]=(b[j]+1ll*a[i]*s[u][j])%mod;
    }
    c[0]=1;
    for(int i=1;i<=m;i++)c[i]=1ll*c[i-1]*x%mod;
    for(int i=0;i<=m;i++)
        ans=(ans+1ll*b[i]*c[i]%mod*e[i]%mod)%mod;
    cout<<ans;
    return 0;
}

题目

#1305. 数

题解

https://sxyz.oj.zhou-jk.cn/article/132