CodeForces -1467D Sum of Paths 动态规划
CodeForces -1467D Sum of Paths 动态规划
题意
定义一条好的路径为从任意点出发后恰好进行了\(k\)次移动产生的路径,这条路径的权值和为走过的点的权值和。
进行\(q\)次修改,每次将\(a_k\)改为\(x\),修改后询问此时所有好的路径的权值和。
分析
每次询问,都不会使原来的好路径更改,因为从贡献的角度考虑,只需要知道每个点的贡献次数即可。
这显然是可以DP的。\(dp[i][j]\)表示走了\(j\)步以后,当前点在\(i\)点的路径个数。
\[dp[i][j] = dp[i + 1][j - 1] + dp[i - 1][j-1]
\]
点\(i\)的贡献,枚举\(i\)点作为中间点
\[cnt[i] = \sum dp[i][j] \times dp[i][k - j]
\]
修改O(1)就好了
代码
ll a[5005];
ll c[5005];
ll dp[5005][5005];
int main(){
int n = rd();
int k = rd();
int q = rd();
ll res = 0;
for(int i = 1;i <= n;i++)
a[i] = rd();
for(int i = 1;i <= n;i++)
dp[i][0] = 1;
for(int i = 1;i <= k;i++)
for(int j = 1;j <= n;j++)
dp[j][i] = (dp[j - 1][i - 1] + dp[j + 1][i - 1]) % MOD;
for(int i = 1;i <= n;i++)
for(int j = 0;j <= k;j++)
c[i] = (c[i] + dp[i][j] * dp[i][k - j] % MOD) % MOD;
for(int i = 1;i <= n;i++)
res = (res + a[i] * c[i] % MOD) % MOD;
for(int i = 1;i <= q;i++){
ll tmp = rd();
ll x = rd();
res = (res - a[tmp] * c[tmp] % MOD + MOD) % MOD;
a[tmp] = x;
res = (res + a[tmp] * c[tmp] % MOD + MOD) % MOD;
cout << res << '\n';
}
}