ICPC 西安站 E - Find Maximum

501 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情

E - Find Maximum

We define a function f(x)f(x) over all non-negative integer xx as follows: f(x)={1(x=0)f(x3)+1(x>0xmod3=0)f(x1)+1(x>0xmod30)f(x) = \begin{cases} 1 & (x = 0) \\ f(\frac{x}{3}) + 1 & (x > 0\land x\bmod3 = 0) \\ f(x - 1) + 1 & (x > 0\land x\bmod 3\neq 0) \end{cases} Calculate maxx=lrf(x)\max_{x = l} ^ r f(x).

You need to answer TT queries independently. The first line contains a single integer TT (1T1041\leq T\leq 10 ^ 4).

Each of the next TT lines contains two integers ll and rr (1lr10181\leq l\leq r\leq 10 ^ {18}), representing a query.

中文大意

给我们一段区间让我们去求这段区间上面公式的值

解法

解法其实是我灵光一闪想到的,我当时推了半天发现这个可能和三进制有关所有我就把数字带进去计算,然后发现了规律,在三进制状态下每有一个0答案加1没有一个1答案加2每有一个2答案加3,然后可以了,但是写的时候用贪心wa了然后保险起见用了dp去枚举在哪一位改变

#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <stack>
using namespace std;
using ll = long long;
#define int long long
#define endl '\n'
#define pb push_back
#define NO cout << "NO" << endl;
#define YES cout << "YES" << endl;
#define fi first
#define se second
#define all(x) (x).begin(),(x).end()
#define rep(i,n) for(int i = 1; i <= n; i++)
typedef pair<int,int> PII;
const int N = 2e5 + 10;

using namespace std;
using ll = long long;

const int N = 2e6 + 10;

ll que1[N], tot1, que2[N], tot2, f[N][2];

void solve() {
   ll l, r; scanf("%lld%lld", &l, &r);
   tot2 = tot1 = 0;
   ll res = 0;
   while(l) {
     que1[++tot1] = l % 3;
     l /= 3;
   }
   ll ans = 0;
   while(r) {
     que2[++tot2] = r % 3;
     r /= 3;
   }
   res = ans;
   bool f = false;
   for(int i = tot2; i >= 1; i--) {
      if(que2[i] > que1[i]) f = true;
      if(f) {
          if(que2[i] == 2) {
             res = max(res, ans + 2 + (i - 1) * 3);
          }else {
            if(i == tot2) {
                res = max(res, ans + (i - 1) * 3);
            }else res = max(res, ans + 1 + (i - 1) * 3);
          }
      }
      if(que2[i] == 2) ans += 3;
      else if(que2[i] == 1) ans += 2;
      else ans += 1;
   }
   while(tot1) que1[tot1--] = 0;
   printf("%lld\n", max(res, ans));
}
// 1 2 10 11

int main() {
    int T; scanf("%d", &T);
    while(T--)
    solve();
}