F题题解:
由于 n,a,b的范围极大,我们无法通过模拟或动态规划来解决,必须通过贪心策略和数学推导找出最优解。
我们需要考虑以下几种构造策略,并取其中的最大值:
1. 策略一:只构造 td
这是最基础的策略。如果 bb 的收益非常高,或者 aa 的收益很低,我们可能只需要尽可能多地构造 td。
- 快乐值: n/2×b
2. 策略二:尽可能多构造 qcjjkkt,剩余部分构造 td
如果 a 的收益很高,我们应该优先构造 qcjjkkt。
-
完整构造数量: n/7
-
剩余长度: n%7
-
剩余部分的处理:
剩余的长度如果 ≥2可以用来构造td。但是,如果剩余长度是 6,我们可以把它看作是“借用”了前一个 qcjjkkt 的最后一个字符,从而多构造一个 td。不过在代码逻辑中,剩余部分直接按能放多少个 td 计算(即 剩余长度 / 2)。
-
快乐值: n/7×a+(n%7)/2×b
3. 策略三:混合构造(利用重叠)
这是题目中最巧妙的部分。观察 qcjjkkt 的后缀和 td 的前缀。
- 我们可以构造类似 qcjjkkt + d + td + td... 的模式。
- 代码中体现为尝试构造 n/8 个 qcjjkkt 和 td 的组合块(每个块长 8,包含一个 qcjjkkt 和一个 td),然后处理剩余部分。
- 快乐值: n/8×(a+b)+剩余部分能构造的 td 数量×b
4. 策略四:特殊边界处理(剩余长度补全)
当 a 远大于 b 时,我们需要尽可能多地构造 qcjjkkt,即使剩余长度不够 7,也要想办法凑。
- 代码逻辑中,如果剩余长度 tmp2<7,我们检查是否可以通过减少前面的完整块,来凑出一个完整的 qcjjkkt。
- 例如,剩余长度是 5,我们需要再借 2 个字符。如果前面有足够的完整块(每个块长 8),我们可以拆掉一个块,用剩下的空间和借来的空间凑出一个新的 qcjjkkt。
- 条件: if(tmp1 + tmp2 >= 7) 且 tmp1 >= cns (cns 是凑够 7 需要借的字符数)。
- 快乐值: (tmp1−cns)×(a+b)+(cns+1)×a
代码演示
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N = 500010;
const int mod=1000000007;
void solve(){
int n,a,b;
cin>>n>>a>>b;
int sum=0,tmp1,tmp2,tmp3;
sum=max(sum,b*(n/2));
tmp1=n/7;
tmp2=n%7;
tmp3=min(tmp1,tmp2);
sum=max(sum,a*tmp1+b*tmp3+(tmp2-tmp3)/2*b);
tmp1=n/8;
tmp2=n%8;
sum=max(sum,tmp1*(a+b)+tmp2/2*b);
if(tmp1+tmp2>=7){
int cns=7-tmp2;
if(tmp1>=cns){
tmp1-=cns;
sum=max(sum,tmp1*(a+b)+(cns+1)*a);
}
}
cout<<sum<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int T=1;cin>>T;
while(T--){
solve();
}
return 0;
}

京公网安备 11010502036488号