【CF1467D】Sum of Paths 题解

题目链接

题意简介

一条线段上有 n 个点,机器人每次只能移动到自己相邻的点上,且不能离开这 n 个点。每个点都有分数,分别是 \(a_1,a_2,...,a_n\)。 机器人将从任意一个点开始时,在线段上移动 k 次,每到一个点(包括起始点和重复路过的点),机器人的总分就会加上该点的分数。

现在,我们将对这条线段作 q 次单点点权修改,试求出所有的移动方案的机器人总分的总和。

思路分析

很明显这是一道计数问题。不难看出,每次修改后,每个点在所有方案中一共出现的次数 \(cnt_i\) 是不会改变的。我们只需要先求出 \(cnt_i\),维护答案 \(\sum cnt_i \times a_i\) 就行了。

\(f(step,point)\) 表示已经走了 step 步,且最后一步恰好为点 point 的方案数。显然的,我们可以得出:\(f(s,p)=f(s-1,p-1)+f(s-1,p+1)\)\(f(0,p)=1\)

而这个 \(f(s,p)\) 换一种换一种理解方式:可以表示从点 p 出发,走 s 步的方案数。

于是,我们可以用 \(f(s,p)*f(k-s,p)\) 表示在完整的走 k 步的方案中,第 s 步为点 p 的方案数。

而每个点都可能出现在任何一步中,所以,\(cnt_i=\sum^k_{s=0} f(s,i)*f(k-s,i)\)

至此,问题解决。接下来只要求出一次 \(res = \sum cnt_i \times a_i\) 之后,每次修改把答案更改为 \(res+cnt_i*(x-a_i)\) 就行了。

代码库

#include <cstdio>
typedef long long ll;
const ll mod=1e9+7,N=5e3+5;
ll n,k,q,f[N][N],a[N],cnt[N],tot;
int main(){
    scanf("%lld%lld%lld",&n,&k,&q);
    for(int i=1;i<=n;i++) scanf("%lld",a+i),f[i][0]=1;
    for(int t=1;t<=k;t++){
        f[1][t]=f[2][t-1]; f[n][t]=f[n-1][t-1];
        for(int i=2;i<n;i++) f[i][t]=(f[i-1][t-1]+f[i+1][t-1])%mod;
    }
    for(int i=1;i<=n;i++){
        for(int t=0;t<=k;t++) cnt[i]=(cnt[i]+f[i][t]*f[i][k-t]%mod)%mod;
        tot=(tot+cnt[i]*a[i]%mod)%mod;
    }
    while(q--){
        ll i,x; scanf("%lld%lld",&i,&x);
        tot=(tot+mod-cnt[i]*a[i]%mod+cnt[i]*x%mod)%mod;
        a[i]=x; 
        printf("%lld\n",tot);
    }
    return 0;
}
posted @ 2021-01-10 17:31  喵乖乖喵  阅读(173)  评论(0编辑  收藏  举报

膜拜众神

网安院技术部     ZZY大师     Xinyang 大佬     Wjyyy