[CF1204E]Natasha, Sasha and the Prefix Sums
Natasha, Sasha and the Prefix Sums
题解
很明显,如果我们直接求最大前缀和为某个值时的序列数量是比较困难的,于是我们就先求最大前缀和大于某个值时的序列数量。
记为前缀和大于
的合法序列个数,那么答案为
。
很容易发现根据前缀和构造出来的路径的函数图像一定至少与存在一个交点。
由于求出的
的值是没有意义的,毕竟所有序列构造出来都是大于这个值的,他们的值都与
相等,最后将其加上去即可。
可如何求出这些的值呢?
先给出一个前缀和函数图像

我们可以像计算卡塔兰数一样先将其翻折过来,得到

我们发现,这样的话它的起点与终点此时都是固定的,而它有一定会经过的这条直线,因为它的起终点在直线的两侧,所以满足这样条件的方案数就是从起点
到终点
的路径条数,为
,也就是
的值。
我们最后将其加起来即可。
不过这题模数好奇怪呀
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define MAXN 4005
typedef long long LL;
#define int LL
const int mo=998244853;
const int INF=0x3f3f3f3f;
#define gc() getchar()
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=gc();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
x*=f;
}
int n,m,fac[MAXN],inv[MAXN],f[MAXN],ans,g[MAXN];
void init(){
fac[0]=inv[0]=fac[1]=inv[1]=f[1]=1;
for(int i=2;i<=4e3;i++){
fac[i]=1ll*fac[i-1]*i%mo;
f[i]=1ll*(mo-mo/i)*f[mo%i]%mo;
inv[i]=1ll*inv[i-1]*f[i]%mo;
}
}
int C(int x,int y){
if(x<0||y<0||x<y)return 0;
return 1ll*fac[x]*inv[y]%mo*inv[x-y]%mo;
}
signed main(){
init();read(n);read(m);int d=n-m<1?1:n-m,sum;
for(int i=d;i<=n;i++)g[i]=C(n+m,n-i);
for(int i=d;i<=n;i++)(ans+=g[i])%=mo;
printf("%lld\n",(ans+(d-1LL+mo)*g[d]%mo)%mo);
return 0;
}

浙公网安备 33010602011771号