[abc] abc 253E - Distance Sequence

前言

t a g : tag : tag: 计数 前缀和优化dp
传送门 :

题意 :
给定 N , M N,M N,M询问有多少种序列满足条件

条件如下 :
∀ i   , ( 1 ≤ a [ i ] ≤ M ) \forall i\ ,(1\le a[i] \le M) i ,(1a[i]M)
∣ a ∣ = N |a|=N a=N
∣ a i − a i + 1 ∣ ≥ K |a_i-a_{i+1}|\ge K aiai+1K
即长度 N N N,值域是 M M M,相邻元素的差绝对值大于 K K K

思路 :
状态表示 :
d p [ i ] [ j ] dp[i][j] dp[i][j] i i i个并且以 j j j结尾的方案数

状态转移 :
d p [ i + 1 ] [ j ] = ( d p [ i ] [ 1 ] + . . . . + d p [ i ] [ j − K ] ) + ( d p [ i ] [ j + K ] + . . . . d p [ i ] [ M ] ) dp[i+1][j]=(dp[i][1]+....+dp[i][j-K])+(dp[i][j+K]+....dp[i][M]) dp[i+1][j]=(dp[i][1]+....+dp[i][jK])+(dp[i][j+K]+....dp[i][M])

时间复杂度 O ( N M 2 ) O(NM^2) O(NM2)显然 T L E TLE TLE

但是其实我们并不需要去枚举转移

我们发现,我们可以单独计算出来上一层的 d p [ i ] [ 1 ] + . . . . d p [ i ] [ j − k ] dp[i][1]+....dp[i][j-k] dp[i][1]+....dp[i][jk] 这种状态

显然这里可以使用到 前缀和进行优化

因此时间复杂度将为 O ( N M ) O(NM) O(NM)

code :

ll f[N][N];
ll s[N];
int n,m,k;

void solve(){
	cin>>n>>m>>k;
	
	
	for(int i=1;i<=m;i++) f[1][i] = 1;
	
	for(int i=2;i<=n;i++){
		for(int j=1;j<=m;j++)
		s[j] = (s[j-1]+f[i-1][j])%mod;
		
		for(int j=1;j<=m;j++){
			int l =  j-k ;
			int r =  j+k;
			
			if(k == 0) f[i][j] = (f[i][j]+s[m])%mod;
			else{
				if(l>0) f[i][j] = (f[i][j]+s[l])%mod;
				if(r<=m) f[i][j] = (f[i][j]+s[m] - s[r-1]+mod)%mod;
			}
		}
	}
	ll ans = 0;
	for(int i=1;i<=m;i++)
	ans=(ans+f[n][i])%mod;
	cout<<ans<<endl;
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值