2022icpc西安站部分题解-E

E. Find Maximum

题意:给定边界L和R,算满足L\leqslant x\leqslant R的所有xf(x)的最大值,

其中f(x)满足:f(x)=\left\{ \begin{array}{rcl} 1 & & {x = 0}\\ f(\frac{x}{3})+1 & & {x> 0 \wedge x% 3=0 }\\ f(x - 1)+1 & & {x> 0 \wedge x% 3\neq 0} \end{array} \right.

题解:

打表发现发现了f(x)与x的三进制有关系,即f(x)等于x三进制的每个数相加,再加上三进制数的有效位数。下图从左向右依次是x,x的三进制,f(x)。

于是便是将问题转变为在\left [ L,R\right ]区间中找到三进制的每个数相加再加上三进制数的有效位数最大的值。

 首先分类讨论:

1.如果L的三进制长度小于R的三进制长度,那么答案可能是22...2(R的三进制长度减一个2),或者在100...0(R的三进制长度减一个0)-R之间选择最大值;

2.如果L的三进制长度等于R的三进制长度,那么答案在L-R之间选择最大值。

代码如下:

#pragma GCC optimize(2)
#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <bitset>
#include <unordered_map>
#include <set>
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define endl "\n"
#define pb push_back
#define all(x) x.begin(), x.end()

using namespace std;

const int N = 200010, mod = 1000000007, INF = 1e9;
typedef long long LL;
typedef pair<int, int> PII;

int n, T;
int x;
LL l, r;
int res;

LL f(LL x)
{
    if (x == 0) return 1;
    else if (x % 3 == 0) return f(x / 3) + 1;
    else return f(x - 1) + 1;
}

vector<int> get_third(LL x)
{
    vector<int> q;
    if (x == 0) q.pb(0);
    while (x)
    {
        q.pb(x % 3);
        x /= 3;
    }
    reverse(q.begin(), q.end());
    return q;
}

void text(LL x)
{
    cout << x << " :\t";
    LL t = x;
    vector<int> S = get_third(t);
    
    for (int i : S) cout << i;
    cout << "\t" << f(x) << endl;
}

void cal(vector<int> l, vector<int> r, int pos, int sum, int limitr)
{
    if (limitr)
    {
        int ans = sum + (r.size() - pos) * 2 + r.size();
        res = max(res, ans);
        return ;
    }
    if (pos == r.size())
    {
        int ans = sum + r.size();
        res = max(res, ans);
        return ;
    }
    
    int limit = r[pos];
    cal(l, r, pos + 1, sum + limit, 0);
    if (limit - 1 >= l[pos]) cal(l, r, pos + 1, sum + limit - 1, 1);
}

void solve()
{
//    for (int i = 0; i <= 10; i ++ ) text(i);
    res = 0;
    cin >> l >> r;
    vector<int> L, R;
    L = get_third(l), R = get_third(r);
    if (L.size() < R.size())
    {
        res = (R.size() - 1) * 2 + R.size() - 1;
        
        vector<int> backup;
        backup.pb(1);
        for (int i = 1; i < R.size(); i ++ ) backup.pb(0);
//        reverse(backup.begin(), backup.end());
//        for (int i : backup) cout << i << " ";
        cal(backup, R, 0, 0, 0);
    }
    else
    {
        cal(L, R, 0, 0, 0);
    }
    cout << res << endl;
}

int main()
{
    quick_cin();
    cin >> T;
//    T = 1;
    while (T -- )
    {
        solve();
    }
    return 0;
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值