队友太强了呀…
思路一合并,啪就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[i−1][k−1]+dp[i+1][k−1]
这个方程的状态为: 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][m−k]
然后这问题就解决了…
很自信的终测没结束就写题解,不信还能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
***/