【DP优化】HDU - 627 - Circular Coloring

博客给出HDU 6279题目链接,题意是给出n个白点和m个黑点连成环,求所有环价值(相邻且颜色相同长度的乘积)的和。题解使用dp数组表示链的权值和,给出转移方程,并介绍通过两次前缀和优化,还可对前缀和数组压维及省去一维的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6279


题意:

给出n个白点,m个黑点,连成一个环。一个环的价值是所有相邻且颜色相同的长度的乘积。问所有环价值的和


题解:

d p [ i ] [ j ] [ 2 ] dp[i][j][2] dp[i][j][2]表示第一维的点有 i i i个,第二维有 j j j个,与开头是否相同的,链的权值和。默认第一维是开头。
转移方程应该是:

  • d p [ i ] [ j ] [ 0 ] = ∑ k d p [ k ] [ j ] [ 1 ] ∗ ( i − k ) dp[i][j][0]=\sum_{k}dp[k][j][1]*(i-k) dp[i][j][0]=kdp[k][j][1](ik)
  • d p [ i ] [ j ] [ 1 ] = ∑ k d p [ i ] [ k ] [ 0 ] ∗ ( j − k ) dp[i][j][1]=\sum_{k}dp[i][k][0]*(j-k) dp[i][j][1]=kdp[i][k][0](jk)

这个可以做两次前缀和来进行优化。
直接写空间会炸掉,可以对前缀和数组压一维。
d p [ i ] [ j ] [ 1 ] dp[i][j][1] dp[i][j][1]是没用的,直接变成中间变量,也省了一维

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e3+7;
const int mod=1e9+7;
int dp[N][N],tmp;
int s0[N],ss0[N];
int s1[N],ss1[N];
int main(){
    for(int i=1;i<N;i++){
        dp[i][0]=s0[i]=ss0[i]=i;
    }
    for(int i=1;i<N;i++){
        for(int j=1;j<N;j++){
            tmp=ss0[i];
            dp[i][j]=ss1[j];

            s0[i]=(s0[i]+dp[i][j])%mod;
            ss0[i]=(ss0[i]+s0[i])%mod;

            s1[j]=(s1[j]+tmp)%mod;
            ss1[j]=(ss1[j]+s1[j])%mod;
        }
    }
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        ll ans=0;
        for(int i=1;i<=n;i++){
            ans=(ans+1ll*i*i%mod*dp[m][n-i]%mod)%mod;
        }
        for(int i=1;i<=m;i++){
            ans=(ans+1ll*i*i%mod*dp[n][m-i]%mod)%mod;
        }
        printf("%lld\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值