CF1467D

这道题一开始用了一种错误的DP思路 T T ,错误的把除了最外面4个点以外其他点左右的情况当做了对称的(肯定不是对称的啊啊啊!!)

因为题目前两个样例都是5,非常的小,所以感觉还很对,当然后面会错。

其实离正确的思路差的不是很多,但是最妙的一步没想到。

我们以dp[i][j]表示走了i步刚好到j点的方案数,那么反过来说,从j点开始走i步的方案数也是这个。

所以说一个k步的方案中,中间第s个点是j的方案数正好就是dp[s][j]*dp[k-s][j]  (走s步到j然后再从j走k-s步)

那么我们只要事先把DP数组预处理好之后对每个点在0-k步中的出现求个和,就能获得想要的东西了。

PS:之前错误就是求出DP数组之后用的方法不对,试图用一个看起来很对的玄学办法结果当然WA了

下附代码:

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const ll MOD=1e9+7;
 5 ll n,k,q,dp[5005][5005],a[5005],b[5005];
 6 int main(){
 7     scanf("%lld%lld%lld",&n,&k,&q);
 8     for (int i=1; i<=n; i++){
 9         dp[0][i]=1;
10     }
11     for (int i=1; i<=k; i++){
12         for (int j=1; j<=n; j++){
13             if (j==1) dp[i][j]=dp[i-1][j+1];
14             else if (j==n) dp[i][j]=dp[i-1][j-1];
15             else {
16                 dp[i][j]=(dp[i-1][j+1]+dp[i-1][j-1])%MOD;
17             }
18         }
19     }
20     for (int i=1; i<=n; i++){
21         for (int j=0; j<=k; j++){
22             b[i]=(b[i]+dp[j][i]*dp[k-j][i]%MOD)%MOD;
23         }
24     }
25     ll sum=0;
26     for (int i=1; i<=n; i++){
27         scanf("%lld",&a[i]);
28         sum=(sum+a[i]*b[i]%MOD)%MOD;
29     }   
30    /* for (int i=1; i<=n; i++)
31         printf("%lld ",b[i]);
32     printf("
"); */
33     while (q--){
34         ll x,y;
35         scanf("%lld%lld",&x,&y);
36         sum=((sum+b[x]*y%MOD-a[x]*b[x]%MOD)%MOD+MOD)%MOD;
37         a[x]=y;
38         printf("%lld
",sum);
39     }
40     return 0;
41 }
View Code
原文地址:https://www.cnblogs.com/i-caigou-TT/p/14363316.html