zoukankan      html  css  js  c++  java
  • 【CF1467D】Sum of Paths 题解

    题目链接

    题意简介

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

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

    思路分析

    很明显这是一道计数问题。不难看出,每次修改后,每个点在所有方案中一共出现的次数 (cnt_i) 是不会改变的。我们只需要先求出 (cnt_i),维护答案 (sum cnt_i imes 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 imes 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
    ",tot);
        }
        return 0;
    }
    
  • 相关阅读:
    SpringBoot使用SpringSession和redis解决session共享问题(nginx反向代理)
    centos7中安装和配置nginx和keepalived
    定位
    css
    css美化
    html5
    列表,表格,媒体元素
    表单
    一期测试错题修改
    字符串
  • 原文地址:https://www.cnblogs.com/Qing-LKY/p/CF1467D-solution.html
Copyright © 2011-2022 走看看