关于CF的一个DP题目的另一种思想
  • 板块学术版
  • 楼主Qin_windlight
  • 当前回复1
  • 已保存回复1
  • 发布时间2025/7/25 19:50
  • 上次更新2025/7/26 10:16:23
查看原帖
关于CF的一个DP题目的另一种思想
1490511
Qin_windlight楼主2025/7/25 19:50

https://www.luogu.com.cn/problem/CF2075D

有一个想法,不知道对不对(虽然没调好) 就是这道题说除以2k2^k,每一个k只能使用一次。那我们可不可以将x和y转化为二进制,然后从高位至低位比较两者什么时候有差异,将不同的位数记为cnt1和cnt2,由于想要操作最小,然后将这个转化为两个背包问题来解决?

但是由于自己太菜了,不知道这种对不对,来问问大佬们

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int INF = 1e18;

int dp[605][605];


void work () {
    int x, y;
    cin >> x >> y;

    if(x == y) {
        cout << 0 << endl;
        return ;
    }

    vector<int> tmp1, tmp2, a, b;

    while (x) {
        tmp1.push_back(x % 2);
        x /= 2;
    }
    while (y) {
        tmp2.push_back(y % 2);
        y /= 2;
    }
    for (int i = tmp1.size() - 1; i >= 0; i --) {
        a.push_back(tmp1[i]);
    }
    for (int i = tmp2.size() - 1; i >= 0; i --) {
        b.push_back(tmp2[i]);
    }

    int sum1 = 0, sum2 = 0;

    for (int i = 0; i < min(a.size(), b.size()); i ++) {
        if (a[i] != b[i]) {
            sum1 = a.size() - i;
            sum2 = b.size() - i;
            break;
        }
    }
    if (a.size() == 0) {
        cout << (1LL << b.size()) << endl;
        return ;
    }
    if (b.size() == 0) {
        cout << (1LL << a.size()) << endl;
        return ;
    }

    for (int i = 0; i <= 66; i ++) {
        for (int j = 0; j <= 66; j ++) {
            dp[i][j] = INF;
        }
    }

    dp[0][0] = 0;

    for (int k = 1; k <= max(sum1, sum2); k++) {
        for (int i = sum1; i >= 0; i --) {
            for (int j = sum2; j >= 0; j --) {
                if (dp[i][j] == INF) continue;

                if (i + k <= sum1)
                    dp[i + k][j] = min(dp[i + k][j], dp[i][j] + (1LL << k));

                
                if (j + k <= sum2)
                    dp[i][j + k] = min(dp[i][j + k], dp[i][j] + (1LL << k));
            }
        }
    }


    cout << dp[sum1][sum2] << endl;
}

signed main () {   
    int t;
    cin >> t;
    while (t --) {
        work();
    }


    return 0;
}



// 0         0
// 2         2
// 2         2
// 4         4
// 0         0
// 4         4
// 4         4
// 2         0
// 2         0
// 4         4
// 6         8
// 2         0
// 0         0
// 2         0
// 6         8
// 6         8
// 4         0
// 12        1000000000000000000
// 12        1000000000000000000

这是我写了一部分的代码,下面的左边是正确输出,右边是我的输出,看这么大差别我感觉这个思路可能不太对……

2025/7/25 19:50
加载中...