CF1696E 题解
思路
数学题。
答案是唯一的。操作过程从左上到右下不可逆。每个点操作次数的贡献即每个点数的最大值。
类似于递推:
\[dp_{i,0}=dp_{0,i}=1
\]
\[dp_{i,j}=dp_{i-1,j}+dp_{i,j-1}
\]
则答案为划定范围内所有 \(dp\) 数组值的和。
但这样是 \(O(n^2)\) 的。
又发现斜着看这其实是杨辉三角。
\[C_{i+j}^{i}=dp_{i,j}
\]
\[ans=\sum_{i=0}^n \sum_{j=0}^{a_i-1} C_{i+j}^{i}=\sum_{i=0}^n \sum_{j=0}^{a_i-1} dp_{i,j}
\]
经过打表和 OEIS,发现:
\[\sum_{j=0}^{a_i-1} dp_{i,j}=dp_{i+1,a_i-1}
\]
补证明:
\[\sum_{j=0}^{a_i-1} dp_{i,j}=dp_{i,0}+\sum_{j=1}^{a_i-1}dp_{i,j}=dp_{i+1,0}+\sum_{j=1}^{a_i-1}dp_{i,j}=dp_{i+1,a_i -1}
\]
于是可以 \(O(n)\)。
code
int n,a[maxn],ans;
int pw[maxn],inv[maxn];
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int C(int m,int n){
return pw[m]*inv[n]%mod*inv[m-n]%mod;
}
signed main(){
n=read();
for(int i=0;i<=n;i++)a[i]=read();
pw[0]=inv[0]=1;
for(int i=1;i<=maxn-10;i++)pw[i]=pw[i-1]*i%mod,inv[i]=ksm(pw[i],mod-2);
for(int i=0;i<=n;i++)ans+=C(a[i]+i,i+1),ans%=mod;
printf("%lld\n",ans);
}