경로 합계 CodeForces-1467D
Tagscombinatorics dp math * 2200
표제:
좋은 경로를 정의합니다. 어떤 지점에서 시작한 후 정확히 k 개의 움직임이 지나가는 경우에만이 경로의 가중치를 전달 된 지점의 가중치 합계 (반복)로 정의하고 q 번 수정하고 매번 ak를 변경합니다. x에 모든 '좋은'경로의 가중치 합계를 요청합니다.
예를 들면 다음과 같습니다.
5 1 5
3 5 1 4 2
1 9
2 4
3 6
4 6
5 2
첫 번째 자리를 9로 바꾸면 9 5 1 4 2가되고 해당 답은 62입니다.
대답:
dp 동적 프로그래밍
주제에 따라 각 그리드의 기여도를 계산해야합니다 .dp [i] [j]는 j 단계를 수행 한 후 점 i에서 총 경로 수를 나타냅니다. 점
i는 i-1 또는 i +에서 올 수 있습니다 . 1
에서 상태 전이 :
dp [i] [k] = dp [i-1] [k-1] + dp [i + 1] [k-1]
dp [i] [k]는 i 포인트가 어떤 포인트에 도달하기 위해 k 단계를 거쳐야하는 총 경로 수 (반대로
생각하는 것과 동일) 그렇다면 각 포인트의 기여도를 어떻게 고려할까요?
현재 지점 i가 m 걸음을 걸었다면 계획 수는 dp [i] [m]입니다. 총 k 걸음이 있기 때문에 가야 할 km 단계가 있으므로 계획 수는 dp [i] [ mk],이 포인트의 기여도는 ∑ m = 0 m = k dp [i] [m] * dp [i] [mk]
각 수정에 대해 i 번째 포인트의 값을 수정하고 먼저 원래 기여도를 뺍니다. i 번째 포인트의 새로운 기여도를 추가하십시오
암호:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
const int maxn=5e3+9;
const int mod=1e9+7;
ll a[maxn],c[maxn];
ll dp[maxn][maxn];
int main()
{
int n,k,p;
cin>>n>>k>>p;
for(int i=1;i<=n;i++)cin>>a[i];
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;
}
}
ll sum=0;
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++)sum=(sum+(a[i]*c[i])%mod)%mod;
for(int i=1;i<=p;i++)
{
ll pos,x;
cin>>pos>>x;
sum=((sum-(a[pos]*c[pos])%mod)%mod+mod)%mod;
a[pos]=x;
sum=(sum+(a[pos]*c[pos])%mod)%mod;
printf("%lld\n",sum);
}
return 0;
}
/*
Input
5 1 5
3 5 1 4 2
1 9
2 4
3 6
4 6
5 2
Output
62
58
78
86
86
*/