Educational Codeforces Round 144 (Rated for Div. 2) C. Maximum Set

我们要选出最长的子序列,使得每一个数都是前一个数的倍数。因此自然我们可以想到选择最小值然后每次乘2。所以有 l×2kr,即k=log2rl。所以最大的集合大小就是k+1

然后考虑最大的集合中最小值可能不同,我假设符合条件的最小值是l1,则有l1×2kr,所以l1=r2k

其实序列中每一个数也不一定都是前一个数的2倍。但也不可能是大于3倍,因为4倍可以拆成两个2倍,5倍可以拆成一个2倍,一个3倍。

再考虑,3倍至多只有1个。考虑存在两个3倍的情况{x,3x,9x},如果符合条件,则一定存在更优的情况{x,2x,4x,8x}

我们考虑只有一个3倍的情况,应该是l2×3×2k1r,也即l2=r3×2k1。然后考虑有k 个数是前一个数的倍数,可以任选一个替换为3倍。

因此最终答案就是(l1l+1)+(l2l+1)×k

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; //#define int i64 using vi = vector<int>; using pii = pair<int, int>; const i32 inf = INT_MAX / 2; const int mod = 998244353; void solve() { int l, r; cin >> l >> r; int k = log2((double)r / l); cout << k + 1 << " "; int l1 = r / (1 << k); int l2 = r / ((1 << (k - 1)) * 3); cout << (max(0, l1 - l + 1) % mod + max(0, l2 - l + 1) * k % mod) % mod << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while (T--) solve(); return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18539818.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示