codeforces1467D. Sum of Paths

https://codeforces.com/contest/1467/problem/D

这题要修改每个a[i]然后得到最后的值,那么肯定就要求出每个a[i]对最后的答案有多少次贡献

cnt[i][j]表示第i步走到j的位置,前缀有多少可能,num[i][j]第i步从j开始走,走完k步,后缀有多少可能

那么在第i步用到a[j]的方案数就是cnt[i][j]*num[i][j]

这个思路有点像求桥的时候正反跑一遍方案数可以用pre[i]*fpre[i]=sum他就是一个必经点

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=5010;
const int mod=1e9+7;

int n,m,k,tot,cas,ans;
int a[maxl];ll sum[maxl];
ll dp[maxl][maxl],num[maxl][maxl],cnt[maxl][maxl];
bool vis[maxl];
char s[maxl];

inline void prework()
{
	scanf("%d%d%d",&n,&k,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
}

inline void add(ll &x,ll y)
{
	x+=y;
	if(x>=mod)
		x-=mod;
	if(x<0)
		x+=mod;
}

inline ll qp(ll a,ll b)
{
	ll ans=1,cnt=a;
	while(b)
	{
		if(b&1)
			ans=ans*cnt%mod;
		cnt=cnt*cnt%mod;
		b>>=1;
	}
	return ans;
}

inline void mainwork()
{
	for(int i=1;i<=n;i++)
		num[k][i]=1;
	for(int i=k;i>=1;i--)
		for(int j=1;j<=n;j++)
		{
			if(j>1)
				add(num[i-1][j-1],num[i][j]);
			if(j<n)
				add(num[i-1][j+1],num[i][j]);
		}	
	for(int i=1;i<=n;i++)
		cnt[0][i]=1,add(sum[i],num[0][i]);
	for(int i=1;i<=k;i++)
		for(int j=1;j<=n;j++)
		{
			if(j>1)
				add(cnt[i][j],cnt[i-1][j-1]);
			if(j<n)
				add(cnt[i][j],cnt[i-1][j+1]);
			add(sum[j],cnt[i][j]*num[i][j]%mod);
		}
	ll ans=0;
	for(int i=1;i<=n;i++)
		add(ans,sum[i]*a[i]%mod);
	while(m--)
	{
		int i,x;
		scanf("%d%d",&i,&x);
		add(ans,-sum[i]*a[i]%mod);
		a[i]=x;
		add(ans,sum[i]*a[i]%mod);
		printf("%lld\n",ans);
	}
}

inline void print()
{
}

int main()
{
	int t=1;
	//scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/112386677