【Codeforces 1467D】 Sum of Paths | dp、思维

队友太强了呀…

思路一合并,啪就A了呀,很快啊!

题目大意:

定义一条好的路径,当且仅当从任意点出发之后恰好经过了 k k k次移动,定义这条路径的权值为经过点权值 a i a_i ai的总和,进行 q q q次修改,每次将第 a k a_k ak改为 x x x,询问此时所有‘好’路径的权值总和

题目思路:

考虑 n n n 5000 5000 5000,所以可能要 n 2 n^2 n2预处理

如果把每个位置在多少条路径上算出来,那么对于每次修改就比较好解决了。

所以考虑如何把每个位置在多少条路径上计算出来

首先一个方程
d p [ i ] [ k ] = d p [ i − 1 ] [ k − 1 ] + d p [ i + 1 ] [ k − 1 ] dp[i][k] = dp[i-1][k-1] + dp[i+1][k-1] dp[i][k]=dp[i1][k1]+dp[i+1][k1]
这个方程的状态为: d p [ i ] [ k ] dp[i][k] dp[i][k]表示走了 k k k步当前在i点的路径总数

那么反过来想,这个 d p [ i ] [ k ] dp[i][k] dp[i][k]也可以表示在 i i i点还需要走 k k k步能到达任意点的路径总数,就反过来嘛很简单。

所以对于一个点来说,枚举他作为中间点,枚举他作为第 0 0 0步、 1 1 1步、 2 2 2步、 3 3 3步的中间点,所以对于第 i i i个点作为路径的总数显然是:
∑ k = 0 k = m d p [ i ] [ k ] ∗ d p [ i ] [ m − k ] \sum_{k=0}^{k=m}dp[i][k] * dp[i][m-k] k=0k=mdp[i][k]dp[i][mk]

然后这问题就解决了…
很自信的终测没结束就写题解,不信还能hack掉

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17+7;
const ll maxn = 1e6+700;
const ll mod= 1e9+7;
const ll up = 1e13;
const double eps = 1e-9;
template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
ll a[5005],c[5005];
ll dp[5005][5005];
int main(){
    
    
	read(n);read(m);read(p);

	for(int i=1;i<=n;i++) read(a[i]);
	for(int i=1;i<=n;i++) dp[i][0] = 1; 
	
	for(int k=1;k<=m;k++)
		for(int i=1;i<=n;i++)
			dp[i][k] = (dp[i-1][k-1] + dp[i+1][k-1])%mod;
	for(int i=1;i<=n;i++){
    
    
		for(int k=0;k<=m;k++){
    
    
			c[i] = (c[i] + (dp[i][k]*dp[i][m-k])%mod)%mod;
		}
	}
	ll ans = 0;
	for(int i=1;i<=n;i++) ans = (ans + (a[i] * c[i])%mod)%mod;
	for(int i=1;i<=p;i++){
    
    
		ll pos,x;
		read(pos);read(x);
		ans = (ans - (a[pos]*c[pos])%mod + mod)%mod;
		a[pos] = x;
		ans = (ans + (a[pos]*c[pos])%mod)%mod;
		printf("%lld\n",ans);
	}
	return 0;
}
/***
2 3
2 3 2
4 5 4 1 5
***/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/112386522