题解/算法 {D. Colored Balls}

本文讨论了一个关于彩色球的问题,涉及算法设计和动态规划优化。作者分析了一种初始错误的DP解决方案,并解释了如何通过调整DP状态和计算方式,将时间复杂度从N^3降低到N^2,同时在构建过程中实时求得答案。
摘要由CSDN通过智能技术生成

题解/算法 {D. Colored Balls}

@LINK: https://codeforces.com/contest/1954/problem/D;

对于某一个方案 (即选择了若干个颜色), 此时她是一个模板算法 (@LINK: https://editor.csdn.net/md/?not_checkout=1&articleId=137719326匹配若干颜色小球), 如果你不知道正确解法 这题很容易出错…
. 比如{10,10,6}, 他的答案 是可以O(1)求出的; (如果你想出其他O(N)的做法 有可能是错误的, 比如从大到小排序后 每次匹配相邻元素 这是错误的);

此时问题转换为: 对于序列A, 其任意一个子序列{Bi}的价值为 max( max(Bi), (sum(B)+1)/2), 即 我们需要知道{Bi序列的元素和, Bi的最大值};
对A进行排序, 这样枚举A[i]时 她是最大元素 其前面元素均<=A[i];

#错误做法#
DP[i][j]: 形如[..., A[i]]的元素之和为j的序列个数; 于是答案为DP[i][j] * 其价值(即max(A[i], (j+1)/2);
. 可问题在于, 你这样定义DP, 她的时间是N^3的, 即对于(i,j) 她的前驱是(1/2/3/..., j-A[i]), 会超时的;

于是 你想着 把DP定义为 以A[1/2/3/.../i]结尾的序列个数, 这样时间就是N^2的了 因为(i,j)的前驱只有(i-1)了; 可是此时 你最终得到DP后, 怎么求答案呢? 因为此时 对于DP[i][j] 你并不知道 她的末尾元素是啥…
但其实吧, 这是正确的…
. 最终的DP, 确实无法求出答案; 但是, 其实答案可以在DP构建的过程里 求出来的… 因为(i,j) 等于 (i-1,j) 和 (i-1, j-A[i]) 而其中的(i-1, j-A[i])这个方案 其实就表示A[i]结尾的 和为j的方案个数 (即对应之前的那个正确但超时的DP(i,j)), 因此 此时可以求答案;

int N; cin>> N;
vector<int> A(N);  for( auto & i : A){ cin>> i;}
sort(A.begin(), A.end());
using Mod_ = Modular<int,998244353>;
auto ___GetMinimalGroups = []( int _allCount, int _maxCount){
    return std::max( (_allCount+1)/2, _maxCount);
};
static Mod_ DP[5003][5003];
memset( DP, 0, sizeof(DP));
Mod_ ANS = 0;
{
    DP[0][A[0]] = 1;
    ANS += (DP[0][A[0]] * (Mod_)___GetMinimalGroups(A[0],A[0]));
    DP[0][0] = 1;
    FOR_( i, 1, N-1){
        memcpy( DP[i], DP[i-1], sizeof(DP[i]));
        FOR_( j, A[i], 5000){
            auto const& preDP = DP[ i-1][ j-A[i]];
            auto & nexDP = DP[ i][ j];
            nexDP += preDP;
            //> `[..., A[i]]`(且和为`j`)的方案个数 等于`preDP`;
            ANS += (preDP * (Mod_)___GetMinimalGroups(j, A[i])); 
        }
    }
}
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值