首页 > 其他 > 详细

[CF792C] Divide by Three - dp

时间:2021-04-06 20:58:31      阅读:43      评论:0      收藏:0      [点我收藏+]

[CF792C] Divide by Three - dp

Description

有一个正整数串写在黑板上。 你需要通过删除一些位使得他变成一个不含前导 0 且是 3 的倍数,并且需要删除尽量少的位数。

Solution

\(f[i][j]\) 表示以 \(i\) 为结尾的子序列,值 \(\mod 3=j\),最大长度是多少

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

#define int long long

const int N = 1e6 + 5;

int f[N][3], p[N][3], n, a[N];

signed main()
{
    ios::sync_with_stdio(false);
    string str;
    cin >> str;
    n = str.length();
    for (int i = 1; i <= n; i++)
        a[i] = str[i - 1] - ‘0‘;
    memset(f, -0x3f, sizeof f);
    for (int i = 1; i <= n; i++)
        if (a[i])
            f[i][a[i] % 3] = 1, p[i][a[i] % 3] = -1;
            
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            f[i][j] = max(f[i][j], f[i - 1][j]);
            f[i][j] = max(f[i][j], f[i - 1][((j - a[i]) % 3 + 3) % 3] + 1);
            if (f[i][j] == f[i - 1][((j - a[i]) % 3 + 3) % 3] + 1)
                p[i][j] = 1;
            if (f[i][j] == f[i - 1][j])
                p[i][j] = 0;
        }
    }
    
    if (f[n][0] < 0)
    {
        for (int i = 1; i <= n; i++)
            if (a[i] == 0)
            {
                cout << 0 << endl;
                return 0;
            }
        cout << -1 << endl;
        return 0;
    }
    int pos = 0;
    vector<int> ans;
    for (int i = n; i >= 1; i--)
    {
        if (p[i][pos] == -1)
        {
            ans.push_back(a[i]);
            break;
        }
        else if (p[i][pos] == 1)
        {
            ans.push_back(a[i]);
            pos = (pos - a[i] % 3 + 3) % 3;
        }
    }
    if (ans.size())
        for (int i = ans.size() - 1; i >= 0; i--)
            cout << ans[i];
}

[CF792C] Divide by Three - dp

原文:https://www.cnblogs.com/mollnn/p/14622244.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!