题解:CF1912E【保姆级】
【CF1912E】 Evaluate It and Back Again【保姆级】
前言
- 博客食用更佳~
与楼中的大佬思路相同,有借鉴之处,但本蒻蒟这篇 还算详细,这是来自蒻蒟的发言,不要在意...
前置思维
- 构造。
分析
使得正着读它的结果是 \(p\),倒着读它的结果是 \(q\)。
我们可以想到,让这个式子由两部分构成:
- 正着读可以算出 \(p\) 的值(部分一)。
- 反着读可以算出 \(q\) 的值(部分二)。
这便是 思路:
- 部分一:反着读的值为零。
- 部分二:正着读的值为零。
这样的话,本题似乎只需要用到加法和减法!
如果你有了思路,此灵感会祝你 AC 本题!
具体下面分晓!
构码思路
正读为 p 反读为 0(核心)
我们可以想象一种构造:
以 偶数 考虑!
\[0 + k + k - 0
\]
这样的话,正着读的贡献为 \(2k\),反着读贡献为 \(0\)(对 \(p\) 而言)。
相反 \(q\) 的构造便是:
\[0 - k + k + 0
\]
这样的话,正着读的贡献为 \(0\),反着读贡献为 \(2k\)(对 \(p\) 而言)。
我们便可以得到以下 \(code\):
Code
p /= 2; q /= 2;
//p
if(p > 0) printf("0+%lld+%lld-0+", p, p);
else printf("0%lld%lld+0+", p, p);
//q
q = fzs(q);//翻转数字
if(q > 0) printf("0-%lld+%lld+0", q, q);
else printf("0+%lld%lld-0", -q, q);
翻转数字
emmm...这部分显而易见,开辟一个 \(f = 1\),在原数字除 \(10\) 的同时,\(f\) 乘 \(10\) 加上扣下来的数。
我想 \(code\) 更可以说明方法!
code
lt fzs(lt n){//翻转数字
lt f = 0;
while(n){
f = f*10 + n%10;
n /= 10;
}
return f;
}
其它细节
如果是奇数,\(2k\)的方法会出现问题,但是我们可以用 拆数 的方式进行构造!!!
那怎么拆?我们可以灵活应用 \(12\) 和 \(21\) 相反且一奇一偶的特点:
- 如果均为奇数:我们只需要在序列前加上 \(0+1+0\),然后构造 \(p-1\),\(q-1\)。
- \(p\) 为奇数:我们只需要在序列前加上 \(0+21+0\),然后构造 \(p-21\),\(q-12\)。
- \(q\) 为奇数:我们只需要在序列前加上 \(0+12+0\),然后构造 \(p-12\),\(q-21\)。
小小的BUG
我们考虑害怕 \(q\) 或 \(p\) 翻转后会出现前导零的错误!!!
所以我们可以通过 \(0+2+0\) 的方式构造剩余!!!注意用 while
更为保险!
Code
//害怕出现q翻转后结尾为零
while(p%10 == 0 || q%10 == 0){
p -= 2, q -= 2;
printf("0+2+0+");
}
最后完整 \(code\) 放下面了,里面有注释,助力你 AC 本题!
CODE
#include<bits/stdc++.h>
using namespace std;
typedef long long lt;
lt p, q;
bool pf, qf;//f判断奇偶
lt fzs(lt n){//翻转数字
lt f = 0;
while(n){
f = f*10 + n%10;
n /= 10;
}
return f;
}
int main(){
scanf("%lld%lld", &p, &q);
if(p % 2) pf = 1; if(q % 2) qf = 1;
//p, q均为奇
if(pf && qf){
printf("0+1+0+");
p -= 1; q -= 1;
}
//p为奇
else if(pf){
printf("0+21+0+");
p -= 21; q -= 12;
}
//q为奇
else if(qf){
printf("0+12+0+");
p -= 12; q -= 21;
}
//害怕出现q翻转后结尾为零
while(p%10 == 0 || q%10 == 0){
p -= 2, q -= 2;
printf("0+2+0+");
}
//开整!
p /= 2; q /= 2;
//p
if(p > 0) printf("0+%lld+%lld-0+", p, p);
else printf("0%lld%lld+0+", p, p);
//q
q = fzs(q);
if(q > 0) printf("0-%lld+%lld+0", q, q);
else printf("0+%lld%lld-0", -q, q);
return 0;
}
//正读有贡献,反着无: 0+k+k-0
//反读有贡献,正着无: 0-k+k+0
后记
- 点赞加关注,AK不迷路!