CF1204E Natasha, Sasha and the Prefix Sums 题解

CF1204E Natasha, Sasha and the Prefix Sums

借鉴了 大佬博客

\(n\)\(1\)\(m\)\(-1\)形成的所有序列的最大前缀和之和,\(n,m \leqslant 1e6\)

\(f[i]\)表示最大前缀和正好等于i的序列的个数,则最后答案为 \(\sum_{i=1}^n i*f[i]\),下面利用容斥来求\(f[i]\):

\(g[i]\)表示最大前缀和正好等于i的序列的个数,则 \(f[i] = g[i+1]-g[i]\)

然后在坐标系上,\(+1\)向右 \(-1\)向上 每种序列看成一个从\((0,0)\)\((n,m)\)的路径

要求最大前缀和大于等于\(k\),即为 存在 \(x-y\geqslant k\) 的点
,则路径必须经过 \(y=x-k\)

即从\((0,0)\)\((n,m)\)经过直线\(y=x-k\)的路径数即为\(g[k]\)

\((0,0)\)关于 \(y=x-k\) 对称得到\((k,-k)\),则\((k,-k)\)\((n,m)\)的路径数即为所求

得到\(g[k]=(n+m,n-k-1)\)

\(f[k]=g[k+1]-g[k]=\binom{n+m}{n-k}-\binom{n+m}{n-k-1}\)

但是要注意\(f,g\)的定义:当\(k \leqslant n-m\)时,最大前缀和不可能为\(k\)\(f[k]\)\(0\)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define inf 0x3f3f3f3f
typedef long long LL;
#define cls(x) memset(x,0,sizeof(x))
#define For(i,j,k) for(register int i=(j);i<=(k);++i)
#define Rep(i,j,k) for(register int i=(j);i>=(k);--i)
#define rint register int
#define il inline
il int read(int x=0,int f=1,char ch='0')
{
    while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return f*x;
}

const int N=2e6+5,mod=998244853;
LL fac[N],ifac[N],ans;
il LL C(int n,int m) { return fac[n]*ifac[n-m]%mod*ifac[m]%mod; }
il LL qpow(LL a,LL b) { LL ret=1; for(;b;b>>=1) {if(b&1) ret=ret*a%mod; a=a*a%mod;} return ret; }
int n,m;

//\binom{n+m}{n-k}-\binom{n+m}{n-k-1}
int main()
{
    // freopen("maxpsum.in","r",stdin);
    // freopen("maxpsum.out","w",stdout);
    n=read(); m=read(); ans=n; fac[0]=ifac[0]=1; 
    For(i,1,n+m) fac[i]=1ll*fac[i-1]*i%mod; 
    ifac[n+m]=qpow(fac[n+m],mod-2); Rep(i,n+m-1,1) ifac[i]=1ll*(i+1)*ifac[i+1]%mod;
    For(i,max(n-m,0),n-1) ans=(ans+1ll*i*(C(n+m,n-i)-C(n+m,n-i-1)+mod)%mod)%mod;
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(CF1204E Natasha, Sasha and the Prefix Sums 题解)